/**
 * CC live video
 * v3.8.3 2022/5/12 */
(function HuodeSceneLive() {
  var VERSION = '3.13.0'

  var Utils = {
    isIE: function () {
      if (!!window.ActiveXObject || 'ActiveXObject' in window)
        return true
      else
        return false
      return false
    },
    getDate: function () {
      var date = new Date()
      return date.getMonth() + '_' + date.getDay() + '_' + date.getHours() + '_' + date.getMinutes() + '_' + date.getSeconds()
    },
    isLowDelay: function () {
      return LivePlayer.delay == 0
    }
  }

  !(function () {
    function startTestVersion(d) {
      var info = d.h5 ? d.h5 : {}

      if (info.lowyerVersion) {
        if (isMax(info.lowyerVersion.v, VERSION)) {
          var date = info.lowyerVersion.expiration
          var msg = info.errorMsg
          log(msg)
          if (Error) {
            throw new Error(msg)
          } else {
            warning(msg)
          }
          return
        }
      }
      if (info.latestVersion) {
        if (isMax(info.latestVersion.v, VERSION)) {
          var notifyMsg = info.notify
          // log(notifyMsg);
          warning(notifyMsg)
          return
        }
      }
    }

    function log(l) {
      if (console.log) {
        console.log(l)
      }
    }

    function warning(l) {
      if (console.warn) {
        console.warn(l)
      }
    }

    //判断v1 是否大于v2
    function isMax(v1, v2) {
      var v1s = v1.split('.')
      var v2s = v2.split('.')
      var index = 0
      var len = v1s.length
      var result = false
      while (index < len - 1) {
        var vv1 = parseInt(v1s[index])
        var vv2 = parseInt(v2s[index])
        if (vv1 > vv2) {
          result = true
          break
        } else if (vv1 < vv2) {
          result = false
          break
        }
        index++
      }
      return result

    }

    function requestError(d) {

    }

    var url = '//view.csslcloud.net/version/version.json?v=' + (new Date().getTime())
    var xmlhttp = null
    try {
      if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
      } else if (window.ActiveXObject) {
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
      }
      if (xmlhttp) {
        xmlhttp.open('GET', url, true)
        xmlhttp.onreadystatechange = function () {
          if (xmlhttp.readyState === 4) {
            if (xmlhttp.status === 200) {
              var versionInfo = JSON.parse(xmlhttp.responseText)
              // log("当前的响应信息-->" + xmlhttp.responseText,versionInfo)
              if (versionInfo) {
                startTestVersion(versionInfo)
              }
            }
          }
        }
        xmlhttp.send()
      }
    } catch (e) {
      log('访问版本信息失败')
    }

  })()

  var DELAY_TIME = 10 * 1000

  function isSupportFlash() {
    var isIE = (navigator.appVersion.indexOf('MSIE') >= 0)
    var hasFlash = true

    if (isIE) {
      try {
        var objFlash = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
      } catch (e) {
        hasFlash = false
      }
    } else {
      if (!navigator.plugins['Shockwave Flash']) {
        hasFlash = false
      }
    }
    return hasFlash
  }

  var LiveSDKReportRule = {}
  window.ccTrackReportRule = LiveSDKReportRule
  // 监听事件注册
  function resgisterReportEvent(name) {
    Pusher.socket.on(name, function(data) {
      if (LiveSDKReportRule.hasOwnProperty(name)) {
        LiveSDKReportRule[name]++
      }
    });
  }
  

  // ccTrack 上报
  var ccTrackLog = {
    retry: 0,
    isFrist: true,
    ccTrackTimer: null,
    ccTrackCount: 0,
    catonDuration: 0,
    isCaton: false,
    catonCount: 0,
    HEART_BEAT: 60000,
    isEnd: false,
    ccTrackTiming: 0,
    waitingTimer: -1,
    playStatus: '',
    disconnectNum: 0,
    videoWaitingTimer: null, // video waiting状态
    videoWaitingCount: 0,
    videoWaitingTotalCount: 0, // wating 总记数
    videoLoadedmetadataTimer: null, // video 首帧到可播放timer 
    videoLoadedmetadataCount: 0, // // video 首帧到可播放计数
    ccTrackStream: '', // 拉流地址
    checkSeek: false, // 检查是否追帧
    init: function () {
      try {
        ccTrack.init({
          business: '2001', // 业务类型 
          roleid: DWLive.viewerid, // 角色id
          userid: DWLive.userid, // 账号id
          roomid: DWLive.roomid, // roomid
          platform: MobileLive.isMobile() ? 'h5-m' : 'h5-pc',
          is_low_delay: Utils.isLowDelay(),
          scene_type: 0,
          event_ver: '2.4',
          appver: VERSION,
          appid: DWLive.userid,
          livestarttime: DWLive.liveCountdown ? 0 : (new Date().getTime() + DWLive.liveCountdown * 1000),
        })
      } catch (error) {
        console.log('init error', error)
      }
    },
    join: function (code, msg) {
      try {
        var join = {
          event: 'join',
          code: code,
          data: msg ? JSON.stringify(msg) : ''
        }
        ccTrack.tragger(join)
      } catch (error) { }
    },
    pusherSucces: function () {
      try {
        var pusherSuccesInfo = {
          event: 'pusher',
          code: 200,
          rid: new Date().getTime(),
          serverDomain: Pusher.options.domain
        }
        ccTrack.tragger(pusherSuccesInfo)
      } catch (error) {
        
      }
    },
    pusherReconnect: function () {
      // console.log('pusher 重连成功')
      const _this = this
      if (this.waitingTimer !== -1) {
        clearTimeout(this.waitingTimer)
        this.waitingTimer = -1
      }
      this.waitingTimer = setTimeout(function () {
        if (MobileLive.isRtsStream && MobileLive.catonNum > 0 && !MobileLive.isIosUc) {
          MobileLive.rtsReplay()
        } else {
          if (_this.disconnectNum > 0) {
            const curLine = _this.getChangeLine()
            DWLive.changeLine(curLine)
            // console.log('pusher重连切换线路---', curLine)
          }
        }
      }, 3000)
      
      this.retry ++ 
      try {
        var reconncetInfo = {
          event: 'pusher',
          code: 201,
          rid: new Date().getTime(),
          retry: this.retry,
          serverDomain: Pusher.options.domain
        }
        ccTrack.tragger(reconncetInfo)
      } catch (error) {
        
      }
    },
    pusherReconnecting: function () {
      try {
        var pusherConnectingInfo = {
          event: 'pusher',
          code: 402,
          rid: new Date().getTime(),
          serverDomain: Pusher.options.domain
        }
        ccTrack.tragger(pusherConnectingInfo)
      } catch (error) {
        
      }
    },
    pusherFailed: function () {
      try {
        var pusherFailedInfo = {
          event: 'pusher',
          code: 401,
          rid: new Date().getTime(),
          serverDomain: Pusher.options.domain
        }
        ccTrack.tragger(pusherFailedInfo)
      } catch (error) {
        
      }
    },
    pusherDisconnect: function () {
      try {
        var pusherDisconnectInfo = {
          event: 'pusher',
          code: 400,
          rid: new Date().getTime(),
          serverDomain: Pusher.options.domain
        }
        ccTrack.tragger(pusherDisconnectInfo)
      } catch (error) {
        
      }
    },
    ccTrackTimerFoo: function () {
      var _this = this
      if (_this.ccTrackTimer) {
        clearInterval(_this.ccTrackTimer)
        _this.ccTrackTimer = null
      }
      _this.ccTrackTimer = setInterval(function () {
        if (_this.isEnd) {
          clearInterval(_this.ccTrackTimer)
          _this.ccTrackTimer = null
          return 
        }
        try {
          _this.ccTrackCount = _this.ccTrackCount + 1
          if (_this.isCaton) {
            _this.catonDuration = _this.catonDuration + (new Date().getTime() - _this.catonTime)
          }
          if (_this.catonDuration >= 60000) {
            _this.isCaton = false
          }
          var catonInfo = {
            event: 'heartbeat',
            code: 200,
            blocktimes: _this.catonCount,
            blockduration: _this.catonDuration >= 60000 ? 0 : _this.catonDuration,
            rid: new Date().getTime(),
            num: _this.ccTrackCount,
            heartinter: 60,
            cdn: _this.ccTrackCDN,
            pusherMsg: {
              serverDomain: Pusher.options.domain,
              msgCount: LiveSDKReportRule
            },
            definition: 0,
            pull_stream_url: _this.ccTrackStream, // 拉流地址
            pull_stream_protocol_type: '', // 拉流协议
          }
          _this.catonCount = 0
          _this.catonDuration = 0
          _this.ccTrackTiming = new Date().getTime()
          ccTrack.tragger(catonInfo)
          
          Object.keys(LiveSDKReportRule).forEach(key => {
            LiveSDKReportRule[key] = 0
          })
        } catch (error) {
          console.log('ccTrackTimer:', error)
        }
      }, _this.HEART_BEAT)
    },
    setUrl: function (ccUrl) {
      var reg = /^http(s)?:\/\/(.*?)\//
      this.ccTrackCDN = reg.exec(ccUrl)[2]
      this.ccTrackStream = ccUrl
    },
    endLive: function () {
      this.isEnd = true
      this.isFrist = true
    },
    getChangeLine: function () {
      var currentLines = DWLive.getLine()
      var currentLineIndex = DWLive.getCurrentLine()
      if ((currentLineIndex + 1 >= currentLines.length)) {
        currentLineIndex = 0
      } else {
        currentLineIndex = currentLineIndex + 1
      }
      return currentLineIndex
    },
    bindVideoEvent: function (videoDom) {
      var _this  = this
      this.isEnd = false
      var h5Video = videoDom
      try {
        h5Video.removeEventListener('loadedmetadata', function(){})
        h5Video.removeEventListener('canplay', function(){})
        h5Video.removeEventListener('playing', function(){})
        h5Video.removeEventListener('waiting', function(){})
      } catch (error) {
      }
      h5Video.addEventListener('loadedmetadata', function () {
        // 首帧加载成功
        _this.startPlayTime = new Date().getTime() 
        if (_this.videoLoadedmetadataTimer) {
          clearInterval(_this.videoLoadedmetadataTimer)
          _this.videoLoadedmetadataCount = 0
        }
        _this.videoLoadedmetadataTimer = setInterval(()=> {
          _this.videoLoadedmetadataCount++
          if (_this.videoLoadedmetadataCount == 2) {
            // 超过2s才显示loading
            $('#videoLoading').css('display', 'flex')
            $('#videoWaiting').css('display', 'none')
          } else if (_this.videoLoadedmetadataCount >= 10) {
            // 超过10s 触发切换线路
            $('#videoLoading').css('display', 'none')
            $('#videoWaiting').css('display', 'none')
            clearInterval(_this.videoLoadedmetadataTimer)
            _this.videoLoadedmetadataCount = 0
            // 连续超过10s的loadedmetadata触发切换线路
            const curLine = _this.getChangeLine()
            DWLive.changeLine(curLine)
          }
        }, 1000)
        // 清空waitingtimer
        if (_this.videoWaitingTimer) {
          clearInterval(_this.videoWaitingTimer)
          _this.videoWaitingCount = 0
        }
        _this.tragger({
          event: 'videoPlayStatus',
          code: 200,
          data: {
            type: 'loadedmetadata',
            time: new Date().getTime()
          }
        })
      })

      h5Video.addEventListener('canplay', function () {
        _this.isSeeking = false       
        if (_this.disconnectNum !== 0) _this.disconnectNum = 0
        _this.playStatus = 'canplay'
        $('#videoLoading').css('display', 'none')
        $('#videoWaiting').css('display', 'none')
        // 清空waitingtimer
        if (_this.videoWaitingTimer) {
          clearInterval(_this.videoWaitingTimer)
          _this.videoWaitingCount = 0
        }
        // 清空首帧计时器
        if (_this.videoLoadedmetadataTimer) {
          clearInterval(_this.videoLoadedmetadataTimer)
          _this.videoLoadedmetadataCount = 0
        }
        // 数据上报
        window.cc_hd_player_canplay && window.cc_hd_player_canplay()
        _this.tragger({
          event: 'videoPlayStatus',
          code: 200,
          data: {
            type: 'canplay',
            time: new Date().getTime()
          }
        })
      })

      h5Video.addEventListener('playing', function () {
        $('#videoLoading').css('display', 'none')
        $('#videoWaiting').css('display', 'none')
        var endPlayTime = new Date().getTime()
        if (_this.isFrist) {
          _this.ccTrackTimerFoo()
          _this.isFrist = false
          try {
            var et = endPlayTime - _this.startPlayTime
            var etInfo = {
              event: 'play',
              et: et,
              code: 200,
              rid: new Date().getTime(),
              cdn: _this.ccTrackCDN
            }
            ccTrack.tragger(etInfo)
          } catch (error) {}
        } 
        // 清空waitingtimer
        if (_this.videoWaitingTimer) {
          clearInterval(_this.videoWaitingTimer)
          _this.videoWaitingCount = 0
        }
        // 清空首帧计时器
        if (_this.videoLoadedmetadataTimer) {
          clearInterval(_this.videoLoadedmetadataTimer)
          _this.videoLoadedmetadataCount = 0
        }
        _this.tragger({
          event: 'videoPlayStatus',
          code: 200,
          data: {
            type: 'playing',
            time: new Date().getTime()
          }
        })
      })

      h5Video.addEventListener('timeupdate', function() {
        if (h5Video.buffered && h5Video.buffered.length === 0) return
        
        var current = h5Video.currentTime
        var endTime = (h5Video.buffered && h5Video.buffered.end(0)) ? h5Video.buffered.end(0) : 0
        var bufferTime = endTime - current
        if (bufferTime <= 0) return
        // 追帧
        if (bufferTime > 45) {
          // 播放中追帧 --- 调整倍速
          h5Video.playbackRate = 1.2
        } else {
          h5Video.playbackRate = 1
        }
      })
      h5Video.addEventListener('waiting', function () {
        // 如果还未启播 waiting return
        if (_this.isFrist) return

        // 启动计时器
        if (_this.videoWaitingTimer) {
          clearInterval(_this.videoWaitingTimer)
          _this.videoWaitingCount = 0
        }
        _this.videoWaitingTimer = setInterval(()=> {
          _this.videoWaitingCount++
          _this.videoWaitingTotalCount++
          if (_this.videoWaitingCount == 2) {
            // 超过2s的卡顿才对外抛出
            window.cc_player_stream_waiting && window.cc_player_stream_waiting()
            // UI展示 ---- UI升级为loading小圆圈
            $('#videoLoading').css('display', 'flex')
            $('#videoWaiting').css('display', 'none')
          }
          if (_this.videoWaitingCount >= 5) {
            $('#videoLoading').css('display', 'none')
            $('#videoWaiting').css('display', 'flex')
            // reset waiting 计时器
            clearInterval(_this.videoWaitingTimer)
            _this.videoWaitingTimer = null
            _this.videoWaitingCount = 0
            // 连续超过5s的waiting触发切换线路
            const curLine = _this.getChangeLine()
            DWLive.changeLine(curLine)
          }
          if (_this.videoWaitingTotalCount >= 30) {
            _this.videoWaitingTotalCount = 0
            // 连续超过30的waiting触发切换线路
            const curLine = _this.getChangeLine()
            DWLive.changeLine(curLine)
          }
        }, 1000)
        _this.tragger({
          event: 'videoPlayStatus',
          code: 200,
          data: {
            type: 'waiting',
            time: new Date().getTime()
          }
        })
      }) 
      h5Video.onerror = function (error) {
        // 播放卡顿线路切换
        if (_this.waitingTimer !== -1) {
          clearTimeout(_this.waitingTimer)
          _this.waitingTimer = -1
        }
        _this.waitingTimer = setTimeout(function () {
          _this.disconnectNum = _this.disconnectNum + 1
          if (_this.disconnectNum > 4) {
            window.cc_player_stream_disconnect && window.cc_player_stream_disconnect()
            return
          }
          const curLine = _this.getChangeLine()
          DWLive.changeLine(curLine)
        }, 3000)

        _this.playError(error)
      }
    },
    playError: function (err) {
      let errInfo = err
      if (typeof err !== 'string') {
        errInfo = JSON.stringify(err)
      }
      try {
        var errorInfo = {
          event: 'play',
          code: 400,
          rid: new Date().getTime(),
          data: {
            msg: errInfo
          }
        }
        //@ts-ignore
        ccTrack.tragger(errorInfo)
      } catch (error) {
        
      }
    },
    pusherPageChange: function (data) { // socket 'page_change'
      try {
        var pageChangeInfo = {
          event: 'pageChange',
          code: 200,
          data: {
            url: data.value.url,
            pusherSendTime: data.pusherSendTime,
            socketId: window.socketId 
          }
        }
        ccTrack.tragger(pageChangeInfo)
      } catch (error) {
      }
    },
    pageChangeFailed: function (data) { // 文档翻页image请求失败
      try {
        var pageChangeInfo = {
          event: 'dpview',
          code: 400,
          data: {
            url: data.completeURI,
            pusherTime: data.time,
            socketId: window.socketId 
          }
        }
        ccTrack.tragger(pageChangeInfo)
      } catch (error) {
      }
    },
    tragger: function (obj) {
      try {
        ccTrack.tragger(obj)
      } catch (error) {}
    }
  }

  //工具类
  var Util = {
    sendAjax: function (url, data, callBack) {
      $.ajax({
        url: url,
        type: 'GET',
        dataType: 'jsonp',
        data: data,
        xhrFields: {
          withCredentials: true
        },
        success: function (data) {
          if (typeof callBack === 'function') {
            callBack && callBack(data)
          } else {
            if (console.log) {
              console.log('onQuestionnairePublish is undefined')
            }
          }
        },
        error: function (e) {
          if (typeof callBack === 'function') {
            callBack({ errorCode: 1, msg: 'request error', result: e })
          } else {
            if (console.log) {
              console.log('onQuestionnairePublish is undefined')
            }
          }
        }
      })

    }
  }
  var DWDpc = {
    DocModeType: { NormalMode: 0, FreeMode: 1 },//设置文档为自由模式或者为跟随模式（0为跟随，1为自由）
    isDPReady: false,
    dpc: {},
    fastMode: true,
    init: function () {
      this.dpc = new Dpc({
        roomId: DWLive.roomid,
        acountId: DWLive.userid,
        token: Pusher.options.key,
        type: 1,
        isOpenWaterMark: parseInt(DWLive.fileProcess, 10),
        roomWatermark: parseInt(DWLive.watermark, 10),
        roomType: 'live'
      })
      $('#drawPanel').css({height: '100%', width: '100%'})
    },
    appendDrawPanel: function () {
      var dp = '<iframe id="dpa" allow-scripts allowfullscreen allowusermedia frameborder="0" style="width: 100%;height:100%;"></iframe>'
      if (MobileLive.isMobile() == 'isMobile') {
        dp = '<iframe id="dpa" allow-scripts allowfullscreen allowusermedia frameborder="0" style="width: 100%;height:100%;pointer-events: none;"></iframe>'
      }
      $('#drawPanel').append(dp)
      // $('div#drawPanel').remove()

      if (typeof window.on_cc_live_db_flip === 'function') {
        window.on_cc_live_db_flip()
      }
    },
    destroy: function () {
      if (this.dpc && this.dpc.dispose) {
        this.dpc.dispose()
      }
      $('#dpa').remove()
    },
    pageChange: function (pc) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.pageChange(pc)
    },
    animationChange: function (ac) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.animationChange(ac)
    },
    history: function (h) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.history(h)
    },
    draw: function (d) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.draw(d)
    },
    clear: function () {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.clear()
    },
    reload: function () {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.reload()
    },
    setDocMode: function (t) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.setFreeDocMode(t)
    },
    getDocs: function (callback) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.getDocs(DWLive.roomid, DWLive.userid, callback)
    },
    changePageTo: function (dId, pI) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.changePageTo(dId, pI)
    },
    showMarquee: function (m) {
      if (!m) return
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.openMarquee(m)
    },
    closeMarquee: function () {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.closeMarquee()
    },
    openBarrage: function (l) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.openBarrage()
    },
    insertBarrage: function (data) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      var ifo
      try {
        ifo = JSON.parse(data)
      } catch (e) {
        ifo = {
          type: 'text',
          content: data
        }
      }
      this.dpc.insertBarrage(ifo)
    },
    closeBarrage: function () {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      this.dpc.closeBarrage()
    },
    docAdapt: function (t) {
      if (!this.isDPReady) {
        return
      }
      if (!this.fastMode) {
        return
      }
      var displayMode = t ? '1' : '2'
      this.dpc.setDisplayMode(displayMode)
    }
  }
  function setCookie(key,value,t){
    var oDate=new Date();
    oDate.setDate(oDate.getDate()+t);
    document.cookie=key+"="+value+"; expires="+oDate.toDateString();
  }
  

  window.isRequesting = false
  window.isLoadAgoraRTC = false
  window.isLoadAliyunRtc = false

  var Interactive = {
    getInteractiveToken: function (interaction) {
      var _this = this
      var deviceType = MobileLive.isMobile() ? 'h5-m' : 'h5-pc'
      var deviceVersion = '3.8.3'
      ajaxPOST('/live/interactive/token?accountId=' + DWLive.userid + '&roomId=' + DWLive.roomid + '&deviceType=' + deviceType + '&deviceVersion=' + deviceVersion, {
        accountId: DWLive.userid,
        roomId: DWLive.roomid,
        userId: DWLive.viewerid,
        username: DWLive.viewername
      }, function (data) {
        if (data.success) {
          var _token = data.data.token
          DWLive.interactionToken = _token
          if (interaction && interaction.likeSwitch) { // 点赞sdk
            var _sdk = ['//frontend.bokecc.com/SDK/interactive/like/1.0.0/LikeSdk.js']
            DWLive.loadScript(_sdk, function () {
              _this.initLike({
                token: _token,
                receiveLikeInfo: function (data) {
                  if (typeof DWLive.receiveLikeInfo === 'function') {
                    DWLive.receiveLikeInfo(data)
                  }
                }
              })
              if (typeof window.on_cc_like_ready === 'function') {
                window.on_cc_like_ready()
              }
            })
          }
          if (interaction && interaction.gift && interaction.gift.giftSwitch) { // 礼物sdk
            var _sdk = ['//frontend.bokecc.com/SDK/interactive/reward/1.0.0/RewardSdk.js']
            DWLive.loadScript(_sdk, function () {
              _this.initGift({
                token: _token,
                receiveRewarInfo: function (data) {
                  if (typeof DWLive.receiveRewardInfo === 'function') {
                    DWLive.receiveRewardInfo(data)
                  }
                }
              })
              if (typeof window.on_cc_gift_ready === 'function') {
                window.on_cc_gift_ready()
              }
            })
          }
          if (interaction && interaction.liveCommerce) { // 直播带货sdk
            // https://frontend.bokecc.com/SDK/interactive/commoditySdk/1.0.0/commoditySdk.js
            var _sdk = ['//frontend.bokecc.com/SDK/interactive/commoditySdk/1.0.0/commoditySdk.js']
            DWLive.loadScript(_sdk, function () {
              try {
                _this.CommoditySdk = new CommoditySdk({
                  token: _token,
                  Event: function (data) {
                    if (typeof DWLive.receiveCommodityInfo === 'function') {
                      DWLive.receiveCommodityInfo(data)
                    }
                  }
                })
                if (typeof window.on_cc_commodity_ready === 'function') {
                  window.on_cc_commodity_ready()
                }
              } catch (error) {
                if (typeof window.on_cc_commodity_error === 'function') {
                  window.on_cc_commodity_error(error)
                }
                return
              }
            })
          }
        } else {
          data.error && console.error(data.error)
          if (typeof DWLive.onInteractiveAuthFailed === 'function') {
            DWLive.onInteractiveAuthFailed(data)
          }
        }
      })
    },
    initGift: function (data) {
      try {
        this.giftsdk = new RewardSdk(data)
      } catch (error) {
        if (typeof window.on_cc_gift_error === 'function') {
          window.on_cc_gift_error(error)
        }
        return
      }
    },
    getRewardList: function () {
      return this.giftsdk.getRewardList()
    },
    getRewardHistoryRecord: function () {
      return this.giftsdk.getRewardHistoryRecord()
    },
    getRewardSpecialEffects: function () {
      return this.giftsdk.getRewardSpecialEffects()
    },
    sendGift: function (data) {
      this.giftsdk.sendReward(data)
    },
    disconnectGift: function () {
      this.giftsdk.disconnect()
    },
    initLike: function (data) {
      try {
        this.likesdk = new LikeSdk(data)
      } catch (error) {
        if (typeof window.on_cc_like_error === 'function') {
          window.on_cc_like_error(error)
        }
        return
      }
    },
    getLikeCount: function () {
      return this.likesdk.getLikeCount()
    },
    addLikeCount: function (data) {
      this.likesdk.addLikeCount(data)
    },
    disconnectLike: function () {
      this.likesdk.disconnect()
    },
    getCommodityList: function (params) {
      return this.CommoditySdk.getCommodityList(params)
    },
    getCommodityDetail: function (id) {
      return this.CommoditySdk.getCommodityDetail(id)
    },
    getCommodityLink: function (params) {
      return this.CommoditySdk.getCommodityLink(params)
    },
    disconnectCommodity: function() {
      this.CommoditySdk.disconnect()
    }
  }

  var DWLive = {
    docInfo : {},
    docDelayTime: 0,
    isLiveing: false,
    DocModeType: { NormalMode: 0, FreeMode: 1 },//设置文档为自由模式或者为跟随模式（0为跟随，1为自由）
    MediaScaleMode: { scale43: '4:3', scale169: '16:9', scaleFull: 'full', scaleNormal: 'normal' },
    getLikeCount () {
      return Interactive.getLikeCount()
    },
    addLikeCount (data) {
      return Interactive.addLikeCount(data)
    },
    getCommodityList (data) {
      return Interactive.getCommodityList(data)
    },
    getCommodityDetail (data) {
      return Interactive.getCommodityDetail(data)
    },
    getCommodityLink (data) {
      return Interactive.getCommodityLink(data)
    },
    disconnectCommodity() {
      Interactive.disconnectCommodity()
    },
    disconnectLike () {
      Interactive.disconnectLike()
    },
    getRewardList() {
      return Interactive.getRewardList()
    },
    getRewardHistoryRecord() {
      return Interactive.getRewardHistoryRecord()
    },
    getRewardSpecialEffects() {
      return Interactive.getRewardSpecialEffects()
    },
    sendGift (data) {
      Interactive.sendGift(data)
    },
    disconnectGift () {
      Interactive.disconnectGift()
    },
    // 获取画板区数据
    getDrawboardData () {
      $.ajax({
        url: '//view.csslcloud.net/api/view/info?userid=' + DWLive.userid + '&roomid=' + DWLive.roomid,
        type: 'GET',
        dataType: 'jsonp',
        success: function (data) {
          if (!data.success) {
            return
          }
  
          if (!data.datas) {
            return
          }
          var datas = data.datas
  
          var meta = datas.meta
          if (!meta) {
            return
          }
  
          LivePlayer.isPublishing = meta.isPublishing
  
          // 没有推流
          if (meta.isPublishing != 1) {
            return
          }
  
          if (!DWDpc.fastMode) {
            var pageChange = meta.pageChange
            if (pageChange && pageChange.length) {
              pageChange.sort(function (p1, p2) {
                return parseInt(p1.time) - parseInt(p2.time)
              })
              var lastPage = pageChange.pop()
              pageChanges = []
              pageChanges.push(JSON.stringify({
                'fileName': lastPage.docName,
                'totalPage': lastPage.docTotalPage,
                'docid': lastPage.encryptDocId,
                'url': lastPage.url,
                'page': lastPage.pageNum,
                'time': lastPage.time,
                'useSDK': lastPage.useSDK
              }))
            }
  
            var animation = meta.animation
            if (animation && animation.length) {
              animation.sort(function (p1, p2) {
                return parseInt(p1.time) - parseInt(p2.time)
              })
              var lastAnimation = animation.pop()
              animations = []
              animations.push(JSON.stringify({
                'fileName': lastAnimation.docName,
                'totalPage': lastAnimation.docTotalPage,
                'docid': lastAnimation.encryptDocId,
                'url': lastAnimation.url,
                'page': lastAnimation.pageNum,
                'time': lastAnimation.time,
                'step': lastAnimation.step
              }))
            }
  
            var draw = meta.draw
            if (draw && draw.length) {
              draws = []
              for (var i = 0; i < draw.length; i++) {
                draws.push(draw[i].data)
              }
            }
          }

          if (MobileLive.isMobile() == 'isMobile' && $.DrawingBoard) {
            $.DrawingBoard.history(meta)
          }
  
          //极速动画获取历史信息
          DWDpc.history(meta)
  
          isHistoryReady = true
        }
      })
    },

    // 重绘画板区
    reDrawDocArea () {
        DrawPanel.clear()
        DWDpc.clear()
        this.getDrawboardData()
    },
    // 重新获取播放地址
    refreshVideo () {
        if (MobileLive.isMobile()) {
          MobileLive.setPlayUrl()
        } else {
          if (LivePlayer.isH5Video()) {
            if (DWLive.isBan) {
              return
            }
            LivePlayer.getH5player().startLive()
            return
          }
        }
    },
    init: function (option) {
      if (typeof option == 'undefined') {
        option = {}
      }
      this.likesdk = null
      this.giftsdk = null
      this.userid = $.trim(option.userid)
      this.roomid = $.trim(option.roomid)
      this.groupid = $.trim(option.groupid)
      this.viewername = $.trim(option.viewername)
      this.viewertoken = $.trim(option.viewertoken)
      this.forcibly = $.trim(option.forcibly)
      this.viewercustomua = $.trim(option.viewercustomua)
      this.language = $.trim(option.language)
      this.viewercustominfo = $.trim(option.viewercustominfo)
      this.ua = $.trim(option.ua)
      this.viewerid = $.trim(option.viewerid)
      this.upid = $.trim(option.upid)
      this.isShowFullScreen = $.trim(option.isShowFullScreen)
      this.isPCH5Live = false
      if (option.pcH5Live) {
        this.isPCH5Live = $.trim(option.pcH5Live.toString()) === 'true' ? true : false
      }
      setCookie('lang', this.language, 100000)
      // console.log("sss--"+DWLive.isPCH5Live)
      if (typeof option.fastMode == 'string') {
        if (option.fastMode === 'false') {
          this.fastMode = false
        } else {
          this.fastMode = true
        }
      } else if (typeof option.fastMode == 'boolean') {
        this.fastMode = option.fastMode
      } else {
        this.fastMode = true
      }
      DWDpc.fastMode = this.fastMode


      this.forceNew = false
      if (typeof option.forceNew === 'boolean') {
        this.forceNew = option.forceNew
      }

      var _this = this
      var scripts = [
        '//static.csslcloud.net/js/socket.io.js',
        '//static.csslcloud.net/js/report.js',
        '//class.csslcloud.net/cctrack/ccTrack.js',
      ]

      var isIE = (navigator.appVersion.indexOf('MSIE') >= 0)
      if (!isIE && MobileLive.isMobile() != 'isMobile' && !window.isLoadAgoraRTC) {
        scripts.push('//static.csslcloud.net/js/p1-4.7.3.js')
        window.isLoadAgoraRTC = true
      }
      var drawPanel = document.getElementById('drawPanel')
      if (DWDpc.fastMode && drawPanel) {
        scripts.push('//image.csslcloud.net/live/1.1.0/web/js/dpc.js?v=' + (new Date()).getTime())
      }

      if (MobileLive.isMobile() == 'isMobile') {
        if ($('#drawPanel').length > 0) {
          //启动极速动画模式
          if (!DWDpc.fastMode) {
            scripts.push('//static.csslcloud.net/js/module/drawingBoard-2.0.0.js')
          }
        }
      } else {
        if (!isSupportFlash()) {

          if (typeof DWLive.onNotSupportFlash === 'function') {
            DWLive.onNotSupportFlash()
          }

          if (this.userid == '18452D400D6B81D5') {
            var lpph = $('#' + LivePlayer.id).parent().height()
            var lppw = $('#' + LivePlayer.id).parent().width()

            var tip = '<div style="z-index: 999999;"><p style="color: #0e0e0e; width: 260px;">您还没有安装flash播放器,请点击'
              + '<a href="http://www.adobe.com/go/getflash" style="color: red;" target="_blank">这里'
              + '</a>安装</p></div>'

            $('#' + LivePlayer.id).append(tip).parent().css('z-index', '999999')

            var lpdh = $($('#' + LivePlayer.id + ' div p')[0]).height()
            var lpdw = $($('#' + LivePlayer.id + ' div p')[0]).width()

            $('#' + LivePlayer.id + ' div').css({
              'margin-left': ((lppw - lpdw - 60) / 2) + 'px',
              'margin-top': ((lpph - lpdh) / 2) + 'px'
            })

            setInterval(function () {
              $('#' + LivePlayer.id).parent().show()
            }, 3000)
          }
        }

        scripts.push(
          '//static.csslcloud.net/js/swfobject.js',
          '//static.csslcloud.net/js/json3.min.js'
        )
      }
      _this.loadScript(scripts, function () {
        // 数据上报初始化
        ccTrackLog.init()
        _this.login(fn)

        function fn() {
          _this.history = new History()
        }
        $('#drawPanel').css({height: '100%', width: '100%'})
        if (MobileLive.isMobile() == 'isMobile' && $.DrawingBoard) {
          var dp = '<canvas id="drawPanel" width="1200" height="1200" style="position: absolute;z-index:2;top:0;left: 0"></canvas>'
            + '<iframe id="dpa" src="" frameborder="0" style="position: absolute;top:0;left: 0"></iframe>'
          $('#drawPanel').append(dp)
          $('div#drawPanel').remove()
          $.DrawingBoard.config()
        }
      })

    },
    getChatCustomEmoji: function () {
      var _this = this
      $.ajax({
        url: '//view.csslcloud.net/live/interaction/chat/emoji',
        type: 'GET',
        dataType: 'json',
        headers:{'X-HD-Token': DWLive.sessionId},
        data: {
          accountId: _this.userid,
          roomId: _this.roomid,
          deviceType: MobileLive.isMobile() ? 'h5-m' : 'h5-pc',
          deviceVersion: VERSION,
        },
        success: function (data) {
          if (data.success) {
            if (data.data && data.data.customEmoji && data.data.customEmoji.length) {
              var customEmoji = {
                customEmojiArr: [],
                customEmojiObj: {}
              }
              data.data.customEmoji.forEach(item => {
                customEmoji.customEmojiArr.push(item.name)
                customEmoji.customEmojiObj[item.name] = item.img
              })
              if (typeof DWLive.onChatCustomEmoji === 'function') {
                DWLive.onChatCustomEmoji(customEmoji)
              }  
            }
          } else {
            console.error('查询自定义表情失败', data.error);
          }
        },
        error: function (error) {
          console.error('查询自定义表情失败', data.error);
        }
      }) 
    },
    login: function (fn) {
      var _this = this
      $.ajax({
        url: '//view.csslcloud.net/api/room/login',
        type: 'GET',
        dataType: 'jsonp',
        data: {
          roomid: this.roomid,
          userid: this.userid,
          groupid: this.groupid,
          viewername: this.viewername,
          viewertoken: this.viewertoken,
          forcibly: this.forcibly,
          viewercustomua: this.viewercustomua,
          viewercustominfo: this.viewercustominfo,
          version: VERSION,
          service: 2,
          client: 4
        },
        success: function (data) {
          if (!data.success) {
            if (typeof DWLive.onLoginError === 'function') {
              DWLive.onLoginError(data)
            }
            ccTrackLog.join(400, data)
            return
          }
          $.ajax({
            url: '//view.csslcloud.net/live/data',
            type: 'GET',
            dataType: 'json',
            headers:{'X-HD-Token': data.datas.viewer.key},
            data: {
              accountId: _this.userid,
              roomId: _this.roomid,
              deviceType: MobileLive.isMobile() ? 'h5-m' : 'h5-pc',
              deviceVersion: VERSION,
            },
            success: function (data) {
              var liveInfo = data.data
              if (!liveInfo) return
              if (liveInfo.template.chat === 1 && liveInfo.accountConfig && liveInfo.accountConfig.customEmojiSwitch === 1) { 
                _this.getChatCustomEmoji() 
              }
              DWLive.chatCharLimit = 300
              var room_settings = data.data.room.settings
              if (room_settings && room_settings.chatCharLimit) {
                DWLive.chatCharLimit = room_settings.chatCharLimit
              }
              if (data.data.meta.dp && data.data.meta.dp.pages && data.data.meta.dp.pages[0]) {
                const docObg = data.data.meta.dp.pages[0]
                Object.assign(DWLive.docInfo,{docId: docObg.docId || '', pageNum: docObg.pageNum || 0})
              }
              var _interaction = data.data.room.settings.interaction
              if (_interaction && (_interaction.likeSwitch || (_interaction.gift && _interaction.gift.giftSwitch) || _interaction.liveCommerce)) {
                Interactive.getInteractiveToken(_interaction)
              }
            },
            error: function (err) {
              return new Error(err)
            }
          }) 
          var isHttps = window.location.protocol === 'https:'
          var host = data.datas.pusherNode.primary
          if (isHttps && host && host.indexOf(':')) {
            var s = host.split(':')
            if (s.length == 2) {
              var port = parseInt(s[1])
              if (!isNaN(port)) {
                var httpsPort = port + 400
                host = s[0] + ':' + httpsPort
              }
            }
          }

          Pusher.options.domain = host
          window.ccTrackReportDomain = host

          var url = document.location.protocol + '//' + host + '/' + data.datas.pusher.nsp
          var key = data.datas.viewer.key
          Pusher.options.pusherUrl = url
          Pusher.options.key = key
          DWLive.viewerid = data.datas.viewer.id
          DWLive.sessionId = data.datas.viewer.key
          DWLive.viewername = data.datas.viewer.name
          DWLive.isBan = data.datas.room.isBan//禁播
          DWLive.liveId = data.datas.liveId
          DWLive.upid = data.datas.upId
          DWLive.multiQuality = data.datas.room.multiQuality
          DWLive.documentDisplayMode = data.datas.room.documentDisplayMode
          DWLive.isBarrage = data.datas.room.barrage
          DWLive.liveCountdown = data.datas.room.liveCountdown
          DWLive.groupId = data.datas.viewer.groupId
          DWLive.fileProcess = data.datas.fileProcess
          DWLive.rtsFlag = data.datas.room.rtsFlag
          DWLive.watermark = data.datas.room.watermark

          // 低延迟直播（非H5低延迟）
          if (data.datas.room && data.datas.room.viewMode) {
            DWLive.viewMode = data.datas.room.viewMode
          }

          // 视频logo
          if (data.datas.videoLogo && data.datas.videoLogo.img) {
            DWLive.videoLogo = data.datas.videoLogo
          }
          //初始化极速动画对象
          var drawPanel = document.getElementById('drawPanel')
          if (DWDpc.fastMode && drawPanel) {
            if ($('#documentDisplayMode').length <= 0) {
              $('body').append('<input id=\'documentDisplayMode\' type=\'hidden\' value=\'\'>')
            }
            $('#documentDisplayMode').val(DWLive.documentDisplayMode)
            DWDpc.isDPReady = true
            DWDpc.appendDrawPanel()
            DWDpc.init()
            window.on_hdLive_drawPanel_complete && window.on_hdLive_drawPanel_complete()
          }
          fn()
          var delay = data.datas.room.delayTime,
            foreignPublish = data.datas.room.foreignPublish
          LivePlayer.delay = delay
          if (delay <= 0) {
            DELAY_TIME = 5 * 1000
          }
          LivePlayer.foreignPublish = foreignPublish

          LivePlayer.openHostMode = data.datas.room.openHostMode
          LivePlayer.dvr = data.datas.room.dvr
          LivePlayer.barrageData = data.datas.room.barrage
          LivePlayer.warmVideoId = data.datas.room.encryptWarmVideoId
          LivePlayer.viewerid = data.datas.viewer.id

          var playerBackgroundImageUri = data.datas.room.playerBackgroundImageUri
          if (!playerBackgroundImageUri) {
            playerBackgroundImageUri = ''
          } else {
            var isHttps = window.location.protocol === 'https:'
            if (isHttps) {
              playerBackgroundImageUri = playerBackgroundImageUri.replace(/http:/g, 'https:')
            }
          }
          LivePlayer.backgroundImageUri = playerBackgroundImageUri

          if (typeof DWLive.playerBackgroundImageUri === 'function') {
            DWLive.playerBackgroundImageUri(playerBackgroundImageUri)
          }

          var playerBackgroundHint = data.datas.room.playerBackgroundHint
          if (!playerBackgroundHint) {
            playerBackgroundHint = ''
          }
          LivePlayer.backgroundHint = playerBackgroundHint

          if (typeof DWLive.playerBackgroundHint === 'function') {
            DWLive.playerBackgroundHint(playerBackgroundHint)
          }

          var announcement = data.datas.announcement
          if (typeof DWLive.onAnnouncementShow === 'function' && announcement) {
            DWLive.onAnnouncementShow(announcement)
          }

          var desc = data.datas.room.desc
          if (typeof DWLive.onLiveDesc === 'function') {
            DWLive.onLiveDesc(desc)
          }

          var count = data.datas.room.showUserCount
          if (typeof DWLive.showUserCount === 'function') {
            DWLive.showUserCount(count)
          }

          var marquee = data.datas.viewer.marquee
          if (typeof DWLive.getMarquee === 'function') {
            DWLive.getMarquee(marquee)
          }

          if (typeof DWLive.onLoginSuccess === 'function') {
            var template = {
              'desc': data.datas.template.desc,
              'type': data.datas.template.type,
              'name': data.datas.template.name,
              'id': data.datas.template.id
            }//返回给用户的模板信息
            var viewer = {
              'id': data.datas.viewer.id,
              'groupId': data.datas.viewer.groupId,
              'name': data.datas.viewer.name
            }//返回给用户的viewer信息;
            var live = data.datas.live//返回给用户的live信息
            var loginInfo = { 'live': live, 'template': template, 'viewer': viewer }
            DWLive.onLoginSuccess(loginInfo)
          }

          var time = data.datas.live
          if (typeof DWLive.onLiveTime === 'function') {
            DWLive.onLiveTime(time)
          }
          ccTrackLog.join(200)
          Pusher.init()
          Lottery.init()
          if (MobileLive.isMobile() == 'isMobile') {
            // 移动端增加rts sdk的判断
            var rtsLibs = []
            if ((DWLive.rtsFlag || DWLive.viewMode === 1) && !window.isLoadAliyunRtc) {
              rtsLibs.push('//image.csslcloud.net/js/aliyun-rts-sdk-2.2.3.js')
              DWLive.loadScript(rtsLibs, function () {
                window.isLoadAliyunRtc = true
                MobileLive.init()
              })
            } else {
              MobileLive.init()
            }
          } else {
            LivePlayer.init()
          }

          switch (data.datas.template.type) {
            case 6:
              Qa.init()
              DWLive.sendPublicChatMsg = DWLive.sendPrivateChatMsg = function () {
                return false
              }
              break
            case 5:
              Chat.init()
              Qa.init()
              DrawPanel.init()
              break
            case 4:
              Chat.init()
              DrawPanel.init()
              DWLive.sendQuestionMsg = function () {
                return false
              }
              break
            case 3:
              Chat.init()
              DWLive.sendQuestionMsg = function () {
                return false
              }
              break
            case 2:
              Chat.init()
              Qa.init()
              break
            default:
              Chat.init()
              Qa.init()
              DrawPanel.init()
          }
        },
        error: function (err) {
          if (typeof DWLive.onLoginError === 'function') {
            DWLive.onLoginError(err)
          }
          ccTrackLog.join(400, err)
        }
      })
    },
    logout: function (value) {
      if (!value) return
      $.ajax({
        url: '//view.csslcloud.net/api/live/logout',
        type: 'GET',
        dataType: 'jsonp',
        timeout: 5000,
        xhrFields: {
          withCredentials: true
        },
        success: function (data) {
          if (typeof value.success === 'function') {
            value.success(data)
          }
        },
        error: function (xhr, status, error) {
          if (typeof value.error === 'function') {
            value.error({ 'errorcode': '100', 'msg': '退出失败', 'info': error })
          }
        }
      })

      Pusher.socket && Pusher.socket.disconnect()
    },

    getScript: function (url, success) {

      var readyState = false,
        script = document.createElement('script')
      script.src = url

      script.onload = script.onreadystatechange = function () {
        if (!readyState && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
          readyState = true
          success && success()
        }
      }
      document.body.appendChild(script)

    },

    loadScript: function (res, callback) {
      if (typeof res === 'string') {
        var _res = res
        res = []
        res.push(_res)
      }
      var _this = this,
        queue = function (fs, cb) {
          _this.getScript(fs.shift(), function () {
            fs.length ? queue(fs, cb) : cb && cb()
          })
        }
      queue(res, callback)

    },

    //改名
    changeNickname: function (name) {
      if (!name || typeof name !== 'string' || name.length > 40) {
        return false
      }
      Pusher.socket && Pusher.socket.emit('change_nickname', name)
    },
    destroy: function () {
      this.closeMarquee()
      this.closeMarqueeDoc()
      if (DWDpc) {
        DWDpc.destroy()
      }
      if (Pusher) {
        Pusher.destroy()
      }
      if (live.interaction) {
        live.interaction.disconnectInteraction(options.viewerId)
      }
      if (LivePlayer) { //  && LivePlayer.isReady  PC
        LivePlayer.destroy()
      }
      if (window.live && window.live.interaction) {
        window.live.interaction.hangupInteraction && window.live.interaction.hangupInteraction()
        window.live.interaction.leaveAgoraRTC()
      }
      if (MobileLive.isRtsStream) {
        MobileLive.isRtsStream = false
        MobileLive.rtsPlayerDestroyed()
      }
      // HuodeSceneLive(window)
    },
    sendPublicChatMsg: function (msg) {
      if (!msg || msg.length > DWLive.chatCharLimit) {
        return
      }
      Pusher.socket && Pusher.socket.emit('chat_message', msg)
    },
    sendPrivateChatMsg: function (touserid, tousername, msg) {
      if (!msg || msg.length > DWLive.chatCharLimit) {
        return
      }
      var h = new Date().getHours(),
        m = new Date().getMinutes(),
        s = new Date().getSeconds()
      m = m > 9 ? m : '0' + m
      s = s > 9 ? s : '0' + s
      var j = {
        'fromuserid': this.viewerid,
        'fromusername': this.viewername,
        'touserid': touserid,
        'tousername': tousername,
        'msg': $.trim(msg),
        'time': h + ':' + m + ':' + s
      }
      Pusher.socket && Pusher.socket.emit('private_chat', JSON.stringify(j))
    },

    sendQuestionMsg: function (content) {
      if (!content || content.length > 300) {
        return
      }

      var j = {
        'action': 'question',
        'value': {
          'userId': this.viewerid,
          'userName': this.viewername,
          'content': content
        }
      }

      try {
        Pusher.socket && Pusher.socket.emit('question', JSON.stringify(j))
      } catch (e) {
      }
    },

    barrage: function (msg, color) {
      // 移动H5暂不支持弹幕功能
      if (MobileLive.isMobile() == 'isMobile') {
        return
      }

      var newm = $.trim(msg)
      if (!newm) {
        return
      }
      newm = msg.replace(/\[em2?_([0-9]*)\]/g, '')

      LivePlayer.barrage({
        'txt': newm,
        'color': color == null ? 0xffffff : color
      })
    },

    getDocumentInfo: function () {
      if (Object.keys(DWLive.docInfo).length === 0 || !DWLive.isLiveing) {
        return {};
      }
      return DWLive.docInfo
    },

    getLine: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        var l = MobileLive.getLine()
        return l
      } else {
        return LivePlayer.getLine()
      }
    },
    getCurrentLine: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        var l = MobileLive.getCurrentLine()
        return l
      } else {
        return LivePlayer.getCurrentLine()
      }
    },
    changeQuality: function (quality, callback) {
      if (MobileLive.isMobile() == 'isMobile') {
        return MobileLive.changeQuality(quality, callback)
      } else {
        return LivePlayer.changeQuality(quality, callback)
      }
    },

    getQualityIndex: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        return MobileLive.getQualityIndex()
      } else {
        return LivePlayer.getQualityIndex()
      }
    },

    changeLine: function (line) {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.changeLine(line)
      } else {
        LivePlayer.changeLine(line)
      }
      ccTrackLog.tragger({
        event: 'changeLine',
        code: 200,
        data: {
          line: line
        }
      })
    },

    onlyAudio: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.onlyAudio()
      } else {
        LivePlayer.onlyAudio()
      }
    },
    play: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.play()
      }
    },
    changeVideoScale: function (t) {
      if (MobileLive.isMobile() != 'isMobile') {
        LivePlayer.changeVideoScale(t)
      }
    }
    ,
    setSound: function (n) {
      if (MobileLive.isMobile() == 'isMobile') {
        return
      } else {}
      LivePlayer.setSound(n)
    },

    answerRollcall: function (rid, pid) {
      var j = {
        'rollcallId': rid,
        'userId': this.viewerid,
        'userName': this.viewername,
        'publisherId': pid
      }
      Pusher.socket && Pusher.socket.emit('answer_rollcall', JSON.stringify(j))
    },

    replyVote: function (voteid, option, pid) {
      var j = {
        'voteId': voteid,
        'voteOption': option,
        'publisherId': pid
      }
      Pusher.socket && Pusher.socket.emit('reply_vote', JSON.stringify(j))
    },
    docBarrage: function (msg, color) {
      if (!$.trim(msg)) {
        return
      }
      DrawPanel.barrage({
        'txt': msg,
        'color': color == null ? 0xffffff : color
      })
    },

    openBarrage: function (b) {
      LivePlayer.openBarrage(b)
    },
    openDocBarrage: function (l) {//开启doc弹幕功能
      if (MobileLive.isMobile() == 'isMobile') {
        return
      }
      if (DWDpc.fastMode) {
        DWDpc.openBarrage(l)
      }
    },
    insertDocBarrage: function (data) {//插入弹幕
      if (MobileLive.isMobile() == 'isMobile') {
        return
      }
      if (DWDpc.fastMode) {
        DWDpc.insertBarrage(data)
      }
    },
    closeDocBarrage: function () {//关闭弹幕功能
      if (MobileLive.isMobile() == 'isMobile') {
        return
      }
      if (DWDpc.fastMode) {
        DWDpc.closeBarrage()
      }
    },
    showControl: function (b) {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.showControl(b)
      } else {
        LivePlayer.showControl(b)
      }
    },
    switchFullScreen: function (b) {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.switchFullScreen(b)
      } else {
        LivePlayer.switchFullScreen(b)
      }
    },

    setShowFullScreenBtn: function (e) {
      if (MobileLive.isMobile() === 'isMobile') {
        return
      } else {
        LivePlayer.setShowFullScreenBtn(e)
      }
    },

    livePlayerInit: function () {
      LivePlayer.init()
    },

    openSound: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.setMuted(false)
      } else {
        LivePlayer.openSound()
      }
    },

    closeSound: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.setMuted(true)
      } else {
        LivePlayer.closeSound()
      }
    },

    docAdapt: function (t) {
      if (DWDpc.fastMode) {
        DWDpc.docAdapt(t)
      } else {
        live.adapt = t
      }

    },

    // 请求语音互动
    requestInteraction: function (t) {
      if (window.isRequesting) {
        return
      }
      window.isRequesting = true
      var isIE = (navigator.appVersion.indexOf('MSIE') >= 0)
      if (isIE) {
        return
      }
      live.interaction.requestInteraction(t)
    },

    // 挂断双向视频
    hangupInteraction: function () {
      live.interaction.hangupInteraction()
    },

    // 进入互动房间
    enterInteractionRoom: function (callback) {
      var err = undefined
      try {
        Pusher.socket && Pusher.socket.emit('speak_enter')
      } catch (e) {
        err = e
      } finally {
        if (typeof callback === 'function') callback(err)
      }
    },

    // 发送互动信息
    sendInteractionMessage: function (p, toId, event, data, callback) {
      var type = 'audio'
      if (p.video) {
        type = 'audiovideo'
      }

      var j = {
        type: type,
        fromname: this.viewername,
        fromid: this.viewerid,
        fromrole: 'student',
        toid: toId,
        event: event,
        data: JSON.stringify(data)
      }

      var err = undefined
      try {
        Pusher.socket && Pusher.socket.emit('speak_message', JSON.stringify(j))
      } catch (e) {
        err = e
      } finally {
        if (typeof callback === 'function') callback(err)
      }
    },

    // 视频跑马灯
    showMarquee: function (m) {
      if (MobileLive.isMobile()) {
        MobileLive.showMarquee(m)
      } else {
        LivePlayer.showMarquee(m)
      }
    },
    // 视频跑马灯
    closeMarquee: function () {
      if (MobileLive.isMobile()) {
        MobileLive.closeMarquee()
      } else {
        LivePlayer.closeMarquee()
      }
    },
    showMarqueeDoc: function (m) {
      if (DWDpc.fastMode) {
        DWDpc.showMarquee(m)
      } else {
        DrawPanel.showMarquee(m)
      }
    },
    closeMarqueeDoc: function () {
      if (DWDpc.fastMode) {
        DWDpc.closeMarquee()
      }
    },
    setDocMode: function (t) {
      if (!DWDpc.fastMode) {
        return
      }
      DWDpc.setDocMode(t)
    },
    getDocs: function (callback) {
      if (!DWDpc.fastMode) {
        return
      }
      DWDpc.getDocs(callback)
    },
    changePageTo: function (dId, pI) {
      if (!DWDpc.fastMode) {
        return
      }
      DWDpc.changePageTo(dId, pI)
    },
    // 用户问卷功能提交接口（data -> {"subjectsAnswer":[{"subjectId":"D4D648931609E9B9","selectedOptionId":"306B84236FBD561E"},{"subjectId":"3FFFF7EC39BC96CC","selectedOptionIds":"C5E59BBB4FBD975C,BE571C8FC644B1E1"},{"subjectId":"3CFA9D81528D476B","answerContent":"asdasdasd"}],questionnaireId:'0EDEEC4D0321974B'};
    // callBack->回调返回所有数据）
    submitQuestionnaire: function (_data, callBack) {
      if (!_data) {
        return
      }
      var params = {
        questionnaireid: _data.questionnaireId,
        answers: JSON.stringify({ subjectsAnswer: _data.subjectsAnswer }),
        sessionId: DWLive.sessionId
      }
      $.ajax({
        url: '//eva.csslcloud.net/api/questionnaire/submit',
        type: 'GET',
        dataType: 'jsonp',
        timeout: 5000,
        data: params,
        xhrFields: {
          withCredentials: true
        },
        success: function (data) {
          if (callBack) {
            callBack(data)
          } else {
            if (console.log) {
              console.log('no callback')
            }
          }
        },
        error: function (xhr, status, error) {
          if (callBack) {
            callBack({
              errorCode: 1,
              msg: 'request was aborted', result: error
            })
          }
        }

      })

    },
    commitLottery: function (val, callback) {
      Lottery.commitLottery(val, callback)
    },
    getPublishingQuestionnaire: function (questionnaireId, callBack) {
      var path = '//eva.csslcloud.net/api/questionnaire/info'
      var info = {
        sessionId: DWLive.sessionId
      }
      if (questionnaireId) info.questionnaireid =  questionnaireId
      Util.sendAjax(path, info, callBack)
    },
    getQuestionnairePublishStatis: function (data) {
      var path = '//eva.csslcloud.net/api/questionnaire/statis/info'
      var info = {
        questionnaireid: data.questionnaireId,
        sessionId: DWLive.sessionId
      }
      Util.sendAjax(path, info, DWLive.onQuestionnairePublishStatis)
    },
    //获取随堂测数据
    getPracticeInfo: function (pId, callBack) {
      var path = '//eva.csslcloud.net/api/practice/info'
      var info = {
        practiceId: pId,
        sessionId: Pusher.options.key
      }
      Util.sendAjax(path, info, callBack)
    },
    getPracticeInfomation: function (pId, callBack) {
      var path = '//eva.csslcloud.net/api/practice/info'
      var info = {
        practiceId: pId || '',
        sessionId: Pusher.options.key,
        mark: 1
      }
      Util.sendAjax(path, info, callBack)
    },
    //提交随堂测
    submitPracticeInfo: function (pId, opt, callback) {
      var path = '//eva.csslcloud.net/api/practice/submit'
      var info = {
        practiceId: pId,
        options: opt,
        sessionId: Pusher.options.key
      }
      Util.sendAjax(path, info, callback)
    },
    //获取随堂测统计信息接口API
    getPracticeStatisInfo: function (pId, callback) {
      var path = '//eva.csslcloud.net/api/practice/statis'
      var info = {
        practiceId: pId,
        sessionId: Pusher.options.key
      }
      Util.sendAjax(path, info, callback)
    },
    //获取排名数据接口
    getPracticeRanking: function (pId, callback) {
      var path = '//eva.csslcloud.net/api/practice/ranking'
      // var path = "http://192.168.202.183:8080/api/practice/ranking";
      var info = {
        practiceId: pId,
        sessionId: Pusher.options.key
      }
      Util.sendAjax(path, info, callback)
    },
    //获取打卡信息
    getHdInquirePunchInformation: function (callback) {
      this.httpRequest({
        url: '//view.csslcloud.net/servlet/punch/viewer',
        data: {
          sessionId: Pusher.options.key
        }, success: function (result) {
          if (typeof callback === 'function') {
            callback(result)
          }
        }, error: function (error) {
          callback && callback(error)
        }
      })
    },
    hdCommitPunch: function (pid, callback) {
      this.httpRequest({
        url: '//view.csslcloud.net/servlet/punch/commit',
        data: {
          punchId: pid,
          sessionId: Pusher.options.key
        }, success: function (result) {
          callback && callback(result)
        }, error: function (error) {
          callback && callback(error)
        }
      })
    },
    // 获取当前置顶信息
    hdGetChatTop: function (callback) {
      var _this = this
      $.ajax({
        url: '//view.csslcloud.net/live/interaction/chat/top',
        type: 'GET',
        dataType: 'json',
        headers:{ 
          'X-HD-Token': DWLive.sessionId,
          'Content-Type': 'application/json'
        },
        data: {
          accountId: _this.userid,
          roomId: _this.roomid,
          deviceType: MobileLive.isMobile() ? 'h5-m' : 'h5-pc',
          deviceVersion: VERSION,
        }, success: function (result) {
          callback && callback(result)
        }, error: function (error) {
          callback && callback(error)
        }
      })
    },
    httpRequest: function (options) {
      $.ajax({
        url: options.url || '',
        data: options.data || {},
        type: options.type || 'GET',
        dataType: options.dataType || 'json',
        timeout: options.timeout || 5000,
        success: function (result) {
          if (typeof options.success == 'function') {
            options.success(result)
          }
        },
        error: function (error) {
          if (typeof options.error == 'function') {
            options.error(error)
          }
        },
        fail: function (fail) {
          if (typeof options.fail == 'function') {
            options.fail(fail)
          }
        },
      })
    },
    clipVideoImage: function () {
      if (!this.isPCH5Live && !MobileLive.isMobile()) return

      var cavas = document.createElement('canvas')
      var ctx = cavas.getContext('2d')
      var vd = document.querySelector('#' + LivePlayer.id + ' video')
      if (vd) {
        cavas.width = vd.videoWidth
        cavas.height = vd.videoHeight
        ctx.drawImage(vd, 0, 0, vd.videoWidth, vd.videoHeight)
        return cavas.toDataURL()
      }
      return ''
    }
  }
  window.DWLive = DWLive

  //抽奖2.0
  var Lottery = {
    init: function () {
      this.queryLotteryStatus()
    },
    create: function () {
      this.queryLotteryStatus()
    },
    cancel: function () {
      var params = {
        lotteryStatus: 1,
        haveLottery: true,
       }
      DWLive.onLottery(params)
    },
    complete: function () {
      this.queryLotteryUserInfo()
    },
    /**
     * @查询抽奖状态
     * @param {index, value, lotteryId} 
     * @onLottery 回调函数
     * @params {lotteryId, lotteryStatus, lotteryType, haveLottery: boolean, LotteryUserInfo}
     */
    queryLotteryStatus: function () {
      var _this = this
      ajaxGET('/api/lottery/student/status', {accountId: DWLive.userid, roomId: DWLive.roomid}, function (data) {
        if (data.success && data.data.haveLottery) {
          var resp = data.data
          if (typeof DWLive.onLottery === 'function') {
            _this.lotteryId = data.data.lotteryId
            _this.lotteryType = resp.lotteryType
            var params = {
              lotteryId: resp.lotteryId,
              lotteryStatus: resp.lotteryStatus,
              haveLottery: true,
              lotteryType: resp.lotteryType,
             }
            DWLive.onLottery(params)
          }
        } else {
          if (typeof DWLive.onLottery === 'function') {
            DWLive.onLottery({haveLottery: false})
          }
        }
      })
    },
    queryLotteryUserInfo: function () {
      var _this = this
      ajaxGET('/api/lottery/query/own', {accountId: DWLive.userid, roomId: DWLive.roomid, lotteryId: _this.lotteryId}, function (data) {
        if (data.success) {
          var resp = data.data
          _this.isWinner = resp.isWinner
          _this.collectTemplateInfo = resp.isWinner ? resp.collectTemplate : []
          var params = {
            lotteryId: _this.lotteryId,
            haveLottery: true,
            lotteryStatus: 2,
            lotteryType: _this.lotteryType,
            LotteryWinInfo: {
              LotteryCollectTemplate: resp.collectTemplate || [],
              isWinner: resp.isWinner,
              ownUserInfo: {
                userAvatar: resp.isWinner ? resp.ownUserInfo.userAvatar : '',
                userName: resp.isWinner ? resp.ownUserInfo.userName : '',
                userId: resp.isWinner ? resp.ownUserInfo.userId : '',
                prizeCode: resp.isWinner ? resp.ownUserInfo.prizeCode : ''
              },
              LotteryPrize: resp.prize,
              LotteryUserInfo: resp.userInfos
            }
          }
          DWLive.onLottery(params)
        }
      })
    },
    /**
     * @提交抽奖人信息
     * @param {val, callback} 
     * @val {lotteryId, value}
     * @callback {onError, onSuccess}
     */
    commitLottery: function (val, callback) {
      var _this = this
      var itemName = val.collectInfos.find(function(item) {
        return item.index === 1
      })
      if (itemName.value === '' || itemName.value === ' ') {
        callback && callback.onError && callback.onError('姓名不能未空')
        return
      }
      var itemPhone = val.collectInfos.find(function(item) {
        return item.index === 2
      })
      var myReg = /^[1][3,4,5,7,8,9][0-9]{9}$/
      if (itemPhone) {
        if (!myReg.test(itemPhone.value)) {
          callback && callback.onError && callback.onError('请输入正确的电话号码')
          return
        }
      }
      ajaxPOST('/api/lottery/collect?accountId=' + DWLive.userid + '&roomId=' + DWLive.roomid, val, function (data) {
        if (data.success) {
          callback && callback.onSuccess && callback.onSuccess('提交成功')
          // var params = {
          //   lotteryStatus: 2,
          //   haveLottery: true,
          //  }
          // DWLive.onLottery(params)
        } else {
          callback && callback.onError && callback.onError('提交失败')
        }
      })
    }
  }
  var options = {
    init: function () {
      this['userId'] = DWLive.userid,
        this['roomId'] = DWLive.roomid,
        this['groupId'] = DWLive.groupId,
        this['liveId'] = DWLive.liveId,
        this['viewerId'] = DWLive.viewerid,
        this['upId'] = DWLive.upid
    }
  }

  // Pusher
  var Pusher = {
    options: {
      pusherUrl: '',
      key: '',
      maxMessageCount: 300, // 保存聊天条数
      userId: '',
      roomId: '',
      livePlayerId: '',
      drawPanel: '',
      domain: ''
    },
    drawjson: [],
    pagechangedata: [],
    publishStreamTimer: 0,
    endStreamTimer: 0,

    init: function () {

      var t = MobileLive.isMobile() == 'isMobile' ? 1 : 0
      this.timeIntervalID = -1
      if (!DWLive.forceNew) {
        this.socket = io.connect(this.options.pusherUrl, {
          query: {
            sessionid: Pusher.options.key,
            platform: 1,
            terminal: t
          },
          'secure': true,
          transports: ['websocket']
        })
        debug('forceNew: false')
      } else {
        this.socket = io.connect(this.options.pusherUrl + '?sessionid=' + Pusher.options.key + '&platform=' + 1 + '&terminal=' + t, { forceNew: true })
        debug('forceNew: true')
      }
      this.bind()
    },

    destroy: function () {
      this.hangupInteraction()
      this.cancelRequestInteraction()
      if (this.socket) {
        this.socket.disconnect()
        // io.destroy();
      }

      if (this.timeIntervalID != -1) {
        clearInterval(this.timeIntervalID)
      }
    },
    bind: function () {
      var currentLayout = false
      var _this = this
      this.socket.on('connect', function () {
        window.socketId = _this.socket.io.engine.id
        ccTrackLog.pusherSucces()
        if (typeof window.onSocketConnect === 'function') {
          window.onSocketConnect()
        }
      })

      this.socket.on('disconnect', function () {
        ccTrackLog.pusherDisconnect()
        if (typeof window.onSocketDisconnect === 'function') {
          window.onSocketDisconnect()
        }
        window.isRequesting = false
      })

      this.socket.on('reconnect_failed', function () {
        ccTrackLog.pusherFailed()
      })

      this.socket.on('reconnecting', function () {
        ccTrackLog.pusherReconnecting()
      })

      this.socket.on('reconnect', function () {
        // console.log('重连成功  reconnect----')
        ccTrackLog.pusherReconnect()
      })

      this.socket.on('configuration', function(data) {
        if (!data) return
        data = JSON.parse(data)
        if (!data.report || !data.report.receiving) return
        var pusherReportRule = data.report.receiving
        // 初始化上报值
        pusherReportRule.forEach(element => {
          LiveSDKReportRule[element] = 0
          // 注册上报事件
          resgisterReportEvent(element)
        })     
      })

      // 翻页回调
      this.socket.on('page_change', function (j) {
        var pageData = j
        if (j && typeof (j) === 'string') {
          pageData = JSON.parse(j)
          Pusher.pagechangedata.push(pageData)
        }
        DWLive.docInfo = {
          docId: pageData.value.docid,
          pageNum: pageData.value.page
        }
        if (typeof window.on_cc_live_dw_page_change === 'function') {
          window.on_cc_live_dw_page_change(j)
        }
        if (typeof DWLive.onPageChange === 'function') {
          var obj = JSON.parse(j)
          var data = {
            docId: obj.value.docid,
            docName: obj.value.fileName,
            docTotalPage: obj.value.totalPage,
            pageNum: obj.value.page
          }
          DWLive.onPageChange(data)
        }
         // 翻页数据上报
         ccTrackLog.pusherPageChange(pageData)
      })


      // 改名
      this.socket.on('change_nickname', function (j) {
        DWLive.viewername = j
        if (typeof DWLive.onChangeNickname === 'function') {
          DWLive.onChangeNickname(j)
        }
      })

      // 动画翻页
      this.socket.on('animation_change', function (j) {
        if (typeof window.on_cc_live_dw_animation_change === 'function') {
          window.on_cc_live_dw_animation_change(j)
        }
      })

      // 画板回调
      this.socket.on('draw', function (j) {
        if (j && typeof (j) === 'string') {
          Pusher.drawjson.push(JSON.parse(j))
        }
        if (typeof window.on_cc_live_dw_draw === 'function') {
          window.on_cc_live_dw_draw(j)
        }
      })

      this.socket.on('room_user_count', function (j) {
        if (DWLive.onUserCountMessage && typeof DWLive.onUserCountMessage === 'function') {
          DWLive.onUserCountMessage(j)
        }
      })

      // 接入转播
      this.socket.on('hd-rebroadcast-change-to-sender', function(data) {
          // 重新获取播放地址和画板数据
          if (typeof window.acceptRebroadcast === 'function') {
            window.acceptRebroadcast(data)
          }
          DWLive.refreshVideo()
          DWLive.reDrawDocArea()
      })

      // 取消接入转播
      this.socket.on('hd-rebroadcast-change-to-receiver', function(data) {
          // 重新获取播放地址和画板数据
          if (typeof window.stopRebroadcast === 'function') {
              window.stopRebroadcast(data)
          }
          DWLive.refreshVideo()
          DWLive.reDrawDocArea()
      })

      this.socket.on('publish_stream', function (j) {
        this.publishStreamTimer && clearTimeout(this.publishStreamTimer)
        this.publishStreamTimer = setTimeout(function () {
          if (LivePlayer) {
            LivePlayer.isPublishing = 1
          }
          if (LivePlayer && LivePlayer.start) {
            LivePlayer.start()
          }
          if (DWLive && typeof DWLive.onLiveStart === 'function') {
            DWLive.isLiveing = true
            DWLive.onLiveStart(j)
          }
        }, getDelayTime())
      })
      // 结束直播
      this.socket.on('hd-live-stop', function (j) {
        this.endStreamTimer && clearTimeout(this.endStreamTimer)
        this.endStreamTimer = setTimeout(function () {
          if (LivePlayer) {
            LivePlayer.isPublishing = 0
          }
          if (LivePlayer && LivePlayer.end) {
            LivePlayer.end(j)
          }
          if (DrawPanel && DrawPanel.clear) {
            DrawPanel.clear()
          }
          DWDpc.clear()
          if (typeof DWLive.onLiveEnd === 'function') {
            DWLive.isLiveing = false
            DWLive.onLiveEnd(j)
          }
        }, getDelayTime())
      })

      this.socket.on('end_stream', function (j) {
        // this.endStreamTimer && clearTimeout(this.endStreamTimer)
        // this.endStreamTimer = setTimeout(function () {
        //   if (LivePlayer) {
        //     LivePlayer.isPublishing = 0
        //   }
        //   if (LivePlayer && LivePlayer.end) {
        //     LivePlayer.end()
        //   }
        //   if (DrawPanel && DrawPanel.clear) {
        //     DrawPanel.clear()
        //   }
        //   DWDpc.clear()
        //   if (typeof DWLive.onLiveEnd === 'function') {
        //     DWLive.onLiveEnd(j)
        //   }
        // }, getDelayTime())
      })

      this.socket.on('kick_out', function (j) {
        Pusher.socket.disconnect()

        if (typeof DWLive.onKickOut === 'function') {
          DWLive.onKickOut(j)
        }
        if (typeof DWLive.onKickOutMobile === 'function') {
          DWLive.onKickOutMobile(j)
        }
        if (!MobileLive.isIPad() && !MobileLive.isIPhone() && !MobileLive.isAndroid() && !MobileLive.isWindowsPhone() && !LivePlayer.isH5Video()) {
          LivePlayer.getFlash()._kickOff && LivePlayer.getFlash()._kickOff()
        }
      })

      this.socket.on('announcement', function (data) {
        data = toJson(data)

        if (data.action == 'release') {
          if (typeof DWLive.onAnnouncementRelease === 'function') {
            DWLive.onAnnouncementRelease(data.announcement)
          }
        } else if (data.action == 'remove') {
          if (typeof DWLive.onAnnouncementRemove === 'function') {
            DWLive.onAnnouncementRemove(data)
          }
        }
      })
      //禁言通知
      this.socket.on('ban_chat_broadcast', function (data) {
        data = toJson(data)
        if (typeof DWLive.HDBanChatBroadcastWithData === 'function') {
          DWLive.HDBanChatBroadcastWithData(data)
        }
      })
      //进入直播间
      this.socket.on('in_remind', function (data) {
        data = toJson(data)
        var inRemind = {
          "userId": data.userId, //用户ID
          "userName": data.userName, //用户昵称
          "userRole": data.userRole, //用户角色
          "groupId": data.groupId, //分组ID
          "clientType": data.clientType, //接收端   1-讲师；2-助教；3-主持人；4-观看端
          "prefixContent": data.prefixContent, //内容前缀
          "suffixContent": data.suffixContent, //内容后缀
          "remindAction": 1 // 1:进   0:出
        }
        if (typeof DWLive.HDUserRemindWithAction === 'function') {
          console.log('HDUserRemindWithAction', inRemind)
          DWLive.HDUserRemindWithAction(inRemind)
        }
      })
      //退出直播间
      this.socket.on('out_remind', function (data) {
        data = toJson(data)
        var outRemind = {
          "userId": data.userId, //用户ID
          "userName": data.userName, //用户昵称
          "userRole": data.userRole, //用户角色
          "groupId": data.groupId, //分组ID
          "clientType": data.clientType, //接收端   1-讲师；2-助教；3-主持人；4-观看端
          "prefixContent": data.prefixContent, //内容前缀
          "suffixContent": data.suffixContent, //内容后缀
          "remindAction": 0  // 1:进   0:出
        }
        if (typeof DWLive.HDUserRemindWithAction === 'function') {
          console.log('HDUserRemindWithAction', outRemind)
          DWLive.HDUserRemindWithAction(outRemind)
        }
      })
      // 签到功能
      this.socket.on('start_rollcall', function (data) {
        data = toJson(data)
        if (typeof DWLive.onStartRollCall === 'function') {
          DWLive.onStartRollCall(data)
        }
      })
      //打卡功能
      this.socket.on('start_punch', function (data) {
        data = toJson(data)
        if (typeof DWLive.onHdLiveStartPunch === 'function') {
          DWLive.onHdLiveStartPunch(data)
        }
      })
      //结束打卡
      this.socket.on('stop_punch', function (data) {
        data = toJson(data)
        if (typeof DWLive.onHdLiveStopPunch === 'function') {
          DWLive.onHdLiveStopPunch(data)
        }
      })

      // 开始抽奖
      this.socket.on('start_lottery', function (data) {
        data = toJson(data)
        if (typeof DWLive.onStartLottery === 'function') {
          DWLive.onStartLottery(data)
        }
      })

      // 中奖
      this.socket.on('win_lottery', function (data) {
        data = toJson(data)
        if (typeof DWLive.onWinLottery === 'function') {
          DWLive.onWinLottery(data)
        }
      })

      // 结束抽奖
      this.socket.on('stop_lottery', function (data) {
        data = toJson(data)
        if (typeof DWLive.onStopLottery === 'function') {
          DWLive.onStopLottery(data)
        }
      })

      // 开始答题
      this.socket.on('start_vote', function (data) {
        data = toJson(data)
        if (typeof DWLive.onStartVote === 'function') {
          DWLive.onStartVote(data)
        }
      })

      // 结束答题
      this.socket.on('stop_vote', function (data) {
        data = toJson(data)
        if (typeof DWLive.onStopVote === 'function') {
          DWLive.onStopVote(data)
        }
      })

      // 答题结果
      this.socket.on('vote_result', function (data) {
        data = toJson(data)
        if (typeof DWLive.onVoteResult === 'function') {
          DWLive.onVoteResult(data)
        }
      })

      // 禁播
      this.socket.on('ban_stream', function (data) {
        data = toJson(data)
        //h5禁播
        DWLive.isBan = 1
        if (MobileLive.isMobile() == 'isMobile') {
          MobileLive.ban()

        } else {
          LivePlayer.banLive()
        }

        if (typeof DWLive.onBanStream === 'function') {
          DWLive.onBanStream(data)
        }
      })
      // 解禁
      this.socket.on('unban_stream', function (data) {
        data = toJson(data)
        //h5解禁
        DWLive.isBan = 0
        if (MobileLive.isMobile() == 'isMobile') {
          MobileLive.unban()
        } else {
          LivePlayer.unbanLive()
        }

        if (typeof DWLive.onUnBanStream === 'function') {
          DWLive.onUnBanStream(data)
        }
      })

      // 置顶消息
      this.socket.on('chat_top', function(data) {
        data = toJson(data)

          if (typeof DWLive.onChatTop === 'function') {
              DWLive.onChatTop(data)
          }
      })

      // 取消置顶消息
      this.socket.on('chat_top_cancel', function(data) {
          data = toJson(data)

          if (typeof DWLive.onChatTopCancel === 'function') {
              DWLive.onChatTopCancel(data)
          }
      })
    
      window.isSpeakThirdParty = false

      this.socket.on('room_setting', function (data) {
        data = toJson(data)
        if (typeof DWLive.onRoomSetting === 'function') {
          // console.log('room_setting', data)

          window.allowSpeakThirdParty = data.allow_speak_third_party

          if (data.allow_speak_interaction == 'true') {
            window.isSpeakThirdParty = false
          }

          if (window.allowSpeakThirdParty.status == 'true') {
            window.isSpeakThirdParty = true
            data.allow_speak_interaction = 'true'
          }

          if (window.isSpeakThirdParty) {
            // console.log('声网连麦', window.isSpeakThirdParty)
          } else {
            // console.log('WebRTC连麦', window.isSpeakThirdParty)
          }
          DWLive.isLiveing = true
          console.log('onRoomSetting', data)
          DWLive.onRoomSetting(data)
        }
        if (data.layout_video_main != currentLayout) {
          var main = data.layout_video_main
          if (typeof DWLive.onSwitchVideoDoc === 'function') {
            console.log('onSwitchVideoDoc', main)
            DWLive.onSwitchVideoDoc(main)

          }
          currentLayout = main
        }
      })

      //禁言某人发送信息回调
      this.socket.on('silence_user_chat_message', function (data) {

        if (typeof DWLive.onSilenceUserChatMessage === 'function') {
          console.log('onSilenceUserChatMessage', toJson(data))
          DWLive.onSilenceUserChatMessage(toJson(data))
        }
      })

      //禁言
      this.socket.on('ban_delete_chat', function (data) {
        if (typeof DWLive.onBanDeleteChat === 'function') {
          console.log('onBanDeleteChat', toJson(data))
          DWLive.onBanDeleteChat(toJson(data))
        }
      })


      // 讲师接受互动信息
      this.socket.on('accept_speak', function (data) {
        if (typeof window.on_cc_live_accept_interaction === 'function') {
          window.on_cc_live_accept_interaction(toJson(data))
        }
      })

      // 互动信息
      this.socket.on('speak_message', function (data) {
        if (!window.isSpeakThirdParty && typeof window.on_cc_live_interaction_message === 'function') {
          window.on_cc_live_interaction_message(toJson(data))
        }
      })

      // 已经在聊天的列表信息
      this.socket.on('speak_peer_list', function (data) {
        if (typeof window.on_cc_live_interaction_chatusers === 'function') {
          window.on_cc_live_interaction_chatusers(toJson(data))
        }
      })

      // 挂断互动信息
      this.socket.on('speak_disconnect', function (data) {
        if (typeof window.on_cc_live_interaction_disconnect_self === 'function') {
          window.on_cc_live_interaction_disconnect_self(toJson(data))
        }
      })

      this.socket.on('speak_disconnect_third_party', function (data) {
        if (typeof window.on_cc_live_interaction_disconnect_self === 'function') {
          window.on_cc_live_interaction_disconnect_self(toJson(data))
        }
      })

      // 广播信息添加
      this.socket.on('broadcast_msg', function (data) {
        if (typeof DWLive.onBroadcastMsg === 'function') {
          DWLive.onBroadcastMsg(toJson(data).value)
        }
      })

      // 广播信息删除
      this.socket.on('broadcast_action', function (data) {
        if (typeof DWLive.removeBroadcastMsg === 'function') {
          DWLive.removeBroadcastMsg(toJson(data))
        }
      })

      // 发布提问
      this.socket.on('publish_question', function (data) {
        if (typeof DWLive.onQaPublish === 'function') {
          console.log('onQaPublish', toJson(data))
          DWLive.onQaPublish(toJson(data))
        }
      })

      /**
       * 发布问卷
       * */
      this.socket.on('questionnaire_publish', function (data) {
        data = toJson(data)

        if (typeof DWLive.onQuestionnairePublish === 'function') {
          DWLive.onQuestionnairePublish(data)
        }
      })

      /**
       * 结束发布问卷
       * */
      this.socket.on('questionnaire_publish_stop', function (data) {
        data = toJson(data)

        if (typeof DWLive.onQuestionnairePublishStop === 'function') {
          DWLive.onQuestionnairePublishStop(data)
        }
      })
      //发布随堂测功能
      this.socket.on('practice_publish', function (data) {
        data = toJson(data)
        if (typeof DWLive.onPracticePublish === 'function') {
          console.log('onPracticePublish', data)
          DWLive.onPracticePublish(data)
        }
      })
      //停止发布随堂测功能
      this.socket.on('practice_stop', function (data) {
        data = toJson(data)
        if (typeof DWLive.onPracticePublishStop === 'function') {
          DWLive.onPracticePublishStop(data)
        }
      })
      //关闭随堂测功能
      this.socket.on('practice_close', function (data) {
        data = toJson(data)
        if (typeof DWLive.onPracticeClose === 'function') {
          DWLive.onPracticeClose(data)
        }
      })
      // 发布奖杯
      this.socket.on('prize_send', function (data) {
        data = toJson(data)
        if (typeof DWLive.onPrizeSend === 'function') {
          DWLive.onPrizeSend(data)
        }
      })



      /**
       * 发布问卷统计
       * */
      this.socket.on('questionnaire_publish_statis', function (data) {
        data = toJson(data)

        if (typeof DWLive.getQuestionnairePublishStatis === 'function') {
          DWLive.getQuestionnairePublishStatis(data)
        }
      })

      /**
       * @抽奖创建成功推送学生端msg 
      */
      this.socket.on('lottery_create', function (data) {
        Lottery.create(data)
      })
      /**
       * @抽奖取消成功推送学生端msg
      */
      this.socket.on('lottery_cancel', function (data) {
        Lottery.cancel(data)
      })
     /**
      * @抽奖结束成功推送学生端msg
     */
      this.socket.on('lottery_complete', function (data) {
        Lottery.complete(data)
      })

      this.socket.on('room_teachers', function (data) {

        if (typeof DWLive.onOnlineTeachers === 'function') {
          console.log('onOnlineTeachers', toJson(data))
          DWLive.onOnlineTeachers(toJson(data))
        }
      })

      this.socket.on('external_questionnaire_publish', function (data) {
        if (typeof DWLive.onExternalQuestionnairePublish === 'function') {
          DWLive.onExternalQuestionnairePublish(toJson(data))
        }
      })

      this.socket.on('ban_chat', function (data) {
        if (typeof DWLive.onBanChat === 'function') {
          console.log('onBanChat', toJson(data))
          DWLive.onBanChat(toJson(data))
        }
      })

      this.socket.on('unban_chat', function (data) {
        if (typeof DWLive.onUnBanChat === 'function') {
          console.log('onUnBanChat', toJson(data))
          DWLive.onUnBanChat(toJson(data))
        }
      })
      /**
       * 获取当前播放（数据源）场景（0：无意义(默认)，10、11:（开启/关闭）摄像头，20：图片，30：插播视频，40：区域捕获，50：桌面共享，60：自定义场景）
       * **/
      this.socket.on('switch_source', function (data) {
        if (typeof DWLive.onSwitchSource === 'function') {
          console.log('onSwitchSource', data)
          DWLive.onSwitchSource(data)
        }
      })

      var _this = this
      setTimeout(function () {
        try {
          _this.socket.emit('room_user_count')
        } catch (e) {
        }
        try {
          _this.socket.emit('room_teachers')
        } catch (e) {
        }
      }, 1500)
      this.timeIntervalID = setInterval(function () {
        try {
          _this.socket.emit('room_user_count')
        } catch (e) {
        }
        try {
          _this.socket.emit('room_teachers')
        } catch (e) {
        }
      }, 15000)
    },

    // 请求互动
    requestInteraction: function (p, callback) {

      var t = 'audio'

      if (p.video) {
        t += 'video'
      }

      var j = {
        'viewerId': DWLive.viewerid,
        'viewerName': DWLive.viewername,
        'type': t
      }

      var err = undefined
      try {
        this.socket.emit('request_speak', JSON.stringify(j))
      } catch (e) {
        err = e
      } finally {
        if (typeof callback === 'function') callback(err)
      }
    },

    // 取消申请
    cancelRequestInteraction: function (type, callback) {
      var j = {
        'viewerId': DWLive.viewerid,
        'viewerName': DWLive.viewername,
        'type': window.live.interaction.local.type
      }

      debug('interaction', '取消申请：' + JSON.stringify(j))

      var err = undefined
      try {
        this.socket.emit('cancel_request_speak', JSON.stringify(j))
      } catch (e) {
        err = e
      } finally {
        if (typeof callback === 'function') callback(err)
      }
    },

    //挂断互动
    hangupInteraction: function (type, callback) {
      var j = {
        'viewerId': DWLive.viewerid,
        'viewerName': DWLive.viewername,
        'type': type
      }

      debug('interaction', '挂断事件：' + JSON.stringify(j))

      var err = undefined
      try {
        if (window.isSpeakThirdParty) {
          this.socket.emit('hangup_interaction_third_party', JSON.stringify(j))
        } else {
          this.socket.emit('hangup_interaction', JSON.stringify(j))
        }
      } catch (e) {
        err = e
      } finally {
        if (typeof callback === 'function') callback(err)
      }
    }
  }

  /**
   * 语音互动支持
   *
   * */
  var Interaction = function (opts) {
    try {
      window.PeerConnection = (window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection || window.mozRTCPeerConnection)
      window.URL = (window.URL || window.webkitURL || window.msURL || window.oURL)
      window.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia)
      window.nativeRTCIceCandidate = (window.mozRTCIceCandidate || window.RTCIceCandidate)
      window.nativeRTCSessionDescription = (window.mozRTCSessionDescription || window.RTCSessionDescription)
    } catch (e) {
    }

    this.usersPcs = {
      length: 0
    }

    // 本地流信息
    this.local = {
      type: {
        video: false,
        audio: false
      },
      video: {},
      audio: {}
    }

    this.isRequesting = false

    this.client = null
    this.localStream = null

    //声网连麦
    this.initAgoraRTC = function (params) {
      // 当前浏览器是否支持 AgoraRTC
      if (!AgoraRTC.checkSystemRequirements()) {
        ccTrack.tragger({
					event: 'AgoraRTCInitFail',
					code: 400,
          data: {
					  msg: 'Your browser does not support WebRTC!'
          }
				})
      }
      if (AgoraRTC) {
        AgoraRTC.enableLogUpload()
        AgoraRTC.setLogLevel(3)
      }
      if (!window.atob) {
        return
      }

      var self = this
      var accountId = DWLive.userid
      var roomId = DWLive.roomid
      var sessionId = DWLive.sessionId
      var channelId = params.channelId
      var appId = window.atob(this.hex2str(params.appId))
      var viewToken = params.viewToken
      var videoSize = params.videosize
      var uid = 0
      var type = this.local.type

      var options = {
        agora: {
          appId: appId,
          viewToken: viewToken,
          channelId: channelId,
          type: type,
          ui: uid,
          videoSize: videoSize
        },
        tokens: {
          accountId: accountId,
          roomId: roomId,
          sessionId: sessionId,
          channelId: channelId,
          ui: uid
        }
      }

      self.joinAgoraRTC(options)
    }

    this.hex2str = function (hex) {
      var trimedStr = hex.trim()
      var rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr
      var len = rawStr.length
      if (len % 2 !== 0) {
        console.error('Illegal Format ASCII Code!')
        return ''
      }
      var curCharCode
      var resultStr = []
      for (var i = 0; i < len; i = i + 2) {
        curCharCode = parseInt(rawStr.substr(i, 2), 16)
        resultStr.push(String.fromCharCode(curCharCode))
      }
      return resultStr.join('')
    }

    this.joinAgoraRTC = async function (options) {
      if (!AgoraRTC.checkSystemRequirements()) {
				ccTrack.tragger({
					event: 'AgoraRTCInitFail',
					code: 400,
          data: {
					  msg: 'Your browser does not support WebRTC!'
          }
				})
      }
      var self = this
      self.localTracks = {
        audioTrack: null
      };
      if (options.agora.type.video) {
        self.localTracks.videoTrack = null
      }

			self.uid = null
      self.client = await AgoraRTC.createClient({ mode: 'live', codec: 'h264' });

			// 该回调通知远端用户发布了新的音频轨道或者视频轨道。
			self.client.on('user-published', async function (remoteUser, mediaType) {
				// console.log('user-published success')
				var uid = remoteUser.uid;
				await self.client.subscribe(remoteUser, mediaType);
				if (mediaType === "video") {
					var playerNODE = '<div id="interactionRemoteVideo' + uid + '" style="height: 100%; width: 100%;" autoplay></div>';
          $('#videoInteractions').append(playerNODE)
					remoteUser.videoTrack.play(`interactionRemoteVideo${uid}`, { fit: 'contain' });
					
					// 首帧视频解码时触发
					remoteUser.videoTrack.on('first-frame-decoded', function () {
						self.videoAudioTrackOnFirstFrameDecoded()
					})
				}
				if (mediaType === "audio") {
					remoteUser.audioTrack.play();

					// 首帧音频解码时触发
					remoteUser.audioTrack.on('first-frame-decoded', function () {
						self.videoAudioTrackOnFirstFrameDecoded()
					})
				}
			});
      try {
				[ self.uid, self.localTracks.audioTrack ] = await Promise.all([
					self.client.join(options.agora.appId, options.agora.channelId, options.agora.viewToken || null, options.agora.uid || null),
					AgoraRTC.createMicrophoneAudioTrack({ microphoneId: self.microphoneId })
				])
        if (options.agora.type.video) {
          var videoSize = (options.agora.videoSize).split('x');
          self.localTracks.videoTrack = await AgoraRTC.createCameraVideoTrack({ cameraId: self.cameraId })
          await self.localTracks.videoTrack.setEncoderConfiguration({
            // 视频分辨率
            width: parseInt(videoSize[0]),
            height: parseInt(videoSize[1])
          });
        }

				//  发布本地的音视频
        try {
					// "host"（主播）和 "audience"（观众）。主播既可发布轨道，也可订阅轨道；观众不能进行 publish 操作
          if (!$('#agora_local').length) {
              $('#interactionLocalVideo').after('<div id="agora_local"></div>');
          }
          console.log("发布的localTracks", self.localTracks);
					await self.client.setClientRole("host"),
                self.client.publish(Object.values(self.localTracks));
          // console.log("publish success");
        } catch (e) {
          var msg = 'publish failed'
          if (typeof e !== 'string') {
            msg += JSON.stringify(e)
          } else {
            msg += e
          }
          ccTrack.tragger({
            event: 'AgoraRTCPublishFail',
            code: 400,
            data: {
              msg: msg
            }
          })
        }
      } catch (e) {
        var msg = 'join failed'
        if (typeof e !== 'string') {
          msg += JSON.stringify(e)
        } else {
          msg += e
        }
        ccTrack.tragger({
          event: 'AgoraRTCJoinFail',
          code: 400,
          data: {
            msg: msg
          }
        })
      }
			// 通话中质量检测
			/** 
				0	网络质量未知。
				1	网络质量极好。
				2	用户主观感觉和极好差不多，但码率可能略低于极好。
				3	用户主观感受有瑕疵但不影响沟通。
				4	勉强能沟通但不顺畅。
				5	网络质量非常差，基本不能沟通。
				6	完全无法沟通。
			*/
			self.client.on("network-quality", function (stats) {
				var networkQuality = {}
				var localStats = {
					'video': self.client.getLocalVideoStats(),
					'audio': self.client.getLocalAudioStats(),
					'rtt': self.client.getRTCStats().RTT
				};
				networkQuality = {
					'downlinkNetworkQuality': stats.downlinkNetworkQuality, // 下行网络质量
					'uplinkNetworkQuality': stats.uplinkNetworkQuality, // 上行网络质量
					'rtt': localStats.rtt, // SDK 到 Agora 边缘服务器的 RTT (Round-Trip Time)，单位 ms。
					'vfps': localStats.video && localStats.video.sendFrameRate, // 视频帧率 (Firefox 上无法获取该值)
					'vbps': localStats.video && localStats.video.sendBitrate, // 视频码率
					'abps': localStats.audio && localStats.audio.sendBitrate, // 音频码率
					'vpktLossRate': localStats.video && localStats.video.currentPacketLossRate, // 发送的视频 400ms 内的丢包率
					'apktLossRate': localStats.audio && localStats.audio.currentPacketLossRate, // 发送的音频 400ms 内的丢包率
				}
        if (typeof DWLive.onLiveInteractionNetworkQuality === 'function') {
          DWLive.onLiveInteractionNetworkQuality(networkQuality)
        }
			});
			// 关注频道内的异常事件
			self.client.on("exception", function(evt) {
        // 1005 接收视频解码失败
        // 3005 接收视频解码恢复正常
        if (evt.code === 1005 || evt.code === 3005) {
          var exception = {
            code: evt.code,
            msg: evt.msg,
            uid: evt.uid
          }
          if (typeof DWLive.onLiveInteractionException === 'function') {
            DWLive.onLiveInteractionException(exception)
          }
        }
			})
    }

    // 首帧音视频解码时触发
    this.videoAudioTrackOnFirstFrameDecoded = function () {
      var self = this
      if (typeof window.on_cc_live_interaction_remote_media === 'function') {
        window.on_cc_live_interaction_remote_media(self.local.type)
      }
      $('#agora_local').hide()
      // $('#livePlayer').replaceWith('<div id="livePlayer"></div>')
      $('#livePlayer').hide()
      window.isRequesting = false
    }

    this.leaveAgoraRTC = function () {
      var self = this
      //DWLive.livePlayerInit()
      if (!self.client) {
        return
      }

      $('#livePlayer').show()
      LivePlayer.openSound()

      for (var trackName in self.localTracks) {
        var track = self.localTracks[trackName];
        if(track) {
          track.stop();
          track.close();
          self.localTracks[trackName] = undefined;
        }
      }
      self.localTracks = {};
      self.client.leave();
      $('#videoInteractions').empty()
      $('#audioInteractions').empty()
      $('#interactionLocalVideo')[0].src = ''
      $('#agora_local').html('')
      window.isRequesting = false
    }

    this.cameraId = ''
    this.microphoneId = ''

    this.getDevices = function () {
      var self = this
      AgoraRTC.getDevices(function (devices) {
        for (var i = 0; i !== devices.length; ++i) {
          var device = devices[i]
          if (device.kind === 'audioinput' && !self.microphoneId) {
            self.microphoneId = device.deviceId
          }
          if (device.kind === 'videoinput' && !self.cameraId) {
            self.cameraId = device.deviceId
          }
        }
      })
    }

    /**
     * 请求语音互动
     *
     * t = {
     *  video: true,
     *  audio: true
     * }
     * */
    this.requestInteraction = function (t, callback) {
      debug('Interaction', '请求互动')
      window.isSpeakThirdParty && this.getDevices()

      this.local.type = t

      this.isRequesting = true

      // 请求互动超时计时器
      this.setRequestTimeoutTimer()

      // 创建音视频信息
      this.createLocalMedia(function (error) {
        if (error) {
          if (typeof window.on_cc_live_interaction_error === 'function') {
            window.on_cc_live_interaction_error(live.interaction.local.type, error, '创建音视频信息出错')
          }
          return
        }

        Pusher.requestInteraction(t, callback)
      })
    }


    // 语音通话计时器
    this.setCallingTimer = function () {
      live.interaction.interactionTime = 0
      live.interaction.interactionTimeInterval = setInterval(function () {
        ++live.interaction.interactionTime
        if (typeof window.on_cc_live_interaction_interval === 'function') {
          var type = live.interaction.local.type
          var time = live.interaction.interactionTime
          window.on_cc_live_interaction_interval(type, time)
        }
      }, 1000)
    }
    // 清除语音通话计时器
    this.clearCallingTimer = function () {
      live.interaction.interactionTime = 0
      clearInterval(live.interaction.interactionTimeInterval)
    }

    // 互动请求超时定时器
    this.setRequestTimeoutTimer = function () {
      /**
       * 请求互动，60s内没有接受，则自动断开
       *
       * 通知pusher断开
       * */
      live.interaction.REQUEST_INTERACTION_TIMEOUT = setTimeout(function () {
        live.interaction.REQUEST_INTERACTION_TIMEOUT = -1

        // 超时挂断语音通话
        live.interaction.hangupInteraction(DWLive.viewerid)
        live.interaction.stopLocalStream()

        live.interaction.isRequesting = false

        if ($('#interactionLocalVideo')[0]) {
          $('#interactionLocalVideo')[0].src = ''
        }

        if (typeof window.on_cc_live_interaction_request_timeout === 'function') {
          window.on_cc_live_interaction_request_timeout(live.interaction.local.type)
        }
      }, 60000)
      window.isRequesting = false
    }
    // 清空互动请求超时定时器
    this.clearRequestTimeoutTimer = function () {
      if (live.interaction.REQUEST_INTERACTION_TIMEOUT > 0) {
        clearTimeout(live.interaction.REQUEST_INTERACTION_TIMEOUT)
        live.interaction.REQUEST_INTERACTION_TIMEOUT = -1
      }
    }

    // 停止本地流
    this.stopLocalStream = function () {
      if (live.interaction.local.video.stream) {
        try {
          live.interaction.local.video.stream.getTracks().forEach(function (track) {
            track.stop()
          })
        } catch (e) {
        }
      }

      if (live.interaction.local.audio.stream) {
        try {
          live.interaction.local.audio.stream.getTracks().forEach(function (track) {
            track.stop()
          })
        } catch (e) {
        }
      }
    }

    this.cancelInteraction = function () {
      live.interaction.isRequesting = false

      if (typeof window.on_cc_live_interaction_cancal === 'function') {
        window.on_cc_live_interaction_cancal(live.interaction.local.type)
      }
    }

    // 断开连接
    this.disconnectInteraction = function (uId) {
      DWLive.openSound()

      this.clearRequestTimeoutTimer()

      // 删除所有
      if (uId == DWLive.viewerid) {
        $.each(live.interaction.usersPcs, function (userId, up) {
          var pc = up.pc
          if (pc == null) {
            return true
          }

          pc.close()
          pc = null

          if (live.interaction.usersPcs[userId]) {
            delete live.interaction.usersPcs[userId]
            var l = live.interaction.usersPcs.length - 1
            live.interaction.usersPcs.length = l < 0 ? 0 : l
          }

        })
      } else {
        $.each(live.interaction.usersPcs, function (userId, up) {
          var pc = up.pc
          if (!pc) {
            return true
          }

          if (userId != uId) {
            return true
          }

          pc.close()
          pc = null

          if (live.interaction.usersPcs[userId]) {
            delete live.interaction.usersPcs[userId]
            var l = live.interaction.usersPcs.length - 1
            live.interaction.usersPcs.length = l < 0 ? 0 : l
          }
        })
      }

      if (live.interaction.usersPcs.length == 0) {
        this.stopLocalStream()
      }

      live.interaction.isInteractioning = false
      live.interaction.isRequesting = false
    }

    // 创建本地音视频流
    this.createLocalAudioAndVideoMedia = function (c) {
      var that = this
      getUserMedia.call(navigator, {
        video: true,
        audio: true
      }, function (stream) {
        that.local.video.stream = stream

        if (c && typeof c === 'function') {
          c(stream)
        }
      }, function (error) {
        debug('Interaction', 'getUserMedia error: ' + error)

        if (c && typeof c === 'function') {
          c(error)
        }
      })
    }

    // 创建本地音频流
    this.createLocalAudioMedia = function (c) {
      var that = this
      getUserMedia.call(navigator, {
        video: false,
        audio: true
      }, function (stream) {
        that.local.audio.stream = stream

        if (c && typeof c === 'function') {
          c(stream)
        }
      }, function (error) {
        debug('Interaction', 'getUserMedia error: ' + error)

        if (c && typeof c === 'function') {
          c(error)
        }
      })
    }

    this.createLocalMedia = function (c) {
      var that = this
      var type = that.local.type
      getUserMedia.call(navigator, type, function (stream) {
        if (type.video) {
          that.local.video.stream = stream
        } else {
          that.local.audio.stream = stream
        }

        var localVideo = $('#interactionLocalVideo')[0]
        if (localVideo) {
          localVideo.srcObject = stream
          localVideo.volume = 0 // 静音
        }

        if (typeof window.on_cc_live_interaction_local_media === 'function') {
          window.on_cc_live_interaction_local_media(type, stream)
        }

        if (c && typeof c === 'function') {
          c()
        }
      }, function (error) {
        debug('Interaction', 'getUserMedia error: ' + error)

        if (c && typeof c === 'function') {
          c(error)
        }
      })
    }

    this.iceServers = {
      'iceServers': [{
        url: 'stun:turn.csslcloud.net:3478',
        credential: 'bokecc',
        username: 'cc'
      }, {
        url: 'turn:turn.csslcloud.net:3478',
        credential: 'bokecc',
        username: 'cc'
      }],
      'offerExtmapAllowMixed': false
    }

    // 创建被动创建连接的PC
    this.createAnswerPeerConnection = function (chatuser) {
      var pc = new PeerConnection(this.iceServers)

      if (chatuser.type == 'audio') {
        if (!live.interaction.local.audio.stream) {
          this.createLocalAudioMedia()
        }
        pc.addStream(live.interaction.local.audio.stream)
      } else {
        if (!live.interaction.local.video.stream) {
          this.createLocalAudioAndVideoMedia()
        }
        pc.addStream(live.interaction.local.video.stream)
      }

      // 如果检测到媒体流连接到本地，将其绑定到一个audio标签上输出
      pc.onaddstream = function (event) {
        if (typeof window.on_cc_live_interaction_remote_media_self === 'function') {
          window.on_cc_live_interaction_remote_media_self(live.interaction.local.type, chatuser, event.stream)
        }
      }

      pc.createAnswer(function (desc) {
        pc.setLocalDescription(desc)
        // 10.15 chrome M89+ Mextmap-allow-mixed 默认被提供 hack (依赖推流客户端同步升级)
        if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) {
          desc = new RTCSessionDescription({
              type: desc.type,
              sdp: desc.sdp
                  .split('\n')
                  .filter((line) => {
                      return line.trim() !== 'a=extmap-allow-mixed';
                  })
                  .join('\n')
          })
        }
        DWLive.sendInteractionMessage(live.interaction.local.type, chatuser.id, 'answer', desc)
      }, function (error) {
        debug('Interaction', 'Failure callback: ' + error)
      })

      pc.onicecandidate = function (event) {
        if (event.candidate !== null) {
          DWLive.sendInteractionMessage(live.interaction.local.type, chatuser.id, '', event.candidate)
        }
      }

      live.interaction.usersPcs[chatuser.id] = {
        pc: pc,
        user: chatuser
      }

      live.interaction.usersPcs.length += 1
    }

    // 创建主动创建连接的PC
    this.createOfferPeerConnection = function (chatuser) {
      var pc = new PeerConnection(this.iceServers)

      var p = live.interaction.local.type
      if (p.video) {
        pc.addStream(live.interaction.local.video.stream)
      } else {
        pc.addStream(live.interaction.local.audio.stream)
      }

      // 如果检测到媒体流连接到本地，将其绑定到一个audio标签上输出
      pc.onaddstream = function (event) {
        if (typeof window.on_cc_live_interaction_remote_media_self === 'function') {
          window.on_cc_live_interaction_remote_media_self(live.interaction.local.type, chatuser, event.stream)
        }
      }

      pc.oniceconnectionstatechange = function (d) {
        debug('Interaction', 'iceConnectionState ...' + pc.iceConnectionState)

        if (pc.iceConnectionState == 'failed') {
          debug('Interaction', 'iceConnectionState failed')

          live.interaction.hangupInteraction()

          if (typeof window.on_cc_live_interaction_disconnect_self === 'function') {
            window.on_cc_live_interaction_disconnect_self({
              disconnectid: DWLive.viewerid
            })
          }
        }
      }

      pc.createOffer(function (desc) {
        pc.setLocalDescription(desc)
        // 10.15 chrome M89+ Mextmap-allow-mixed 默认被提供 hack (依赖推流客户端同步升级)
        if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) {
          desc = new RTCSessionDescription({
              type: desc.type,
              sdp: desc.sdp
                  .split('\n')
                  .filter((line) => {
                      return line.trim() !== 'a=extmap-allow-mixed';
                  })
                  .join('\n')
          })
        }
        DWLive.sendInteractionMessage(p, chatuser.id, 'offer', desc)
      }, function (error) {
        if (typeof window.on_cc_live_interaction_error === 'function') {
          window.on_cc_live_interaction_error(live.interaction.local.type, error, 'createOfferPeerConnection')
        }
      })

      pc.onicecandidate = function (event) {
        if (event.candidate !== null) {
          DWLive.sendInteractionMessage(p, chatuser.id, '', event.candidate)
        }
      }

      live.interaction.usersPcs[chatuser.id] = {
        pc: pc,
        user: chatuser
      }

      live.interaction.usersPcs.length += 1
    }

    this.id = opts.interaction.id

    // 当前浏览器是否支持互动功能
    this.isSupportInteraction = function () {
      if (window.isSpeakThirdParty) {
        if (!AgoraRTC.checkSystemRequirements()) {
          ccTrack.tragger({
            event: 'AgoraRTCInitFail',
            code: 400,
            data: {
              msg: 'Your browser does not support WebRTC!'
            }
          })
          return false
        } else {
          return true
        }
      } else {
        return window.location.protocol === 'https:' && !!(PeerConnection && URL && getUserMedia && nativeRTCIceCandidate && nativeRTCSessionDescription)
      }
    }

    // 挂断互动
    this.hangupInteraction = function (callback) {
      if (this.isInteractioning) {
        Pusher.hangupInteraction(this.type, callback)
      } else if (this.isRequesting) {
        Pusher.cancelRequestInteraction(this.type, callback)
        this.stopLocalStream()
        this.cancelInteraction()
      } else {
        this.stopLocalStream()
        this.cancelInteraction()
      }
    }
  }

  // LivePlayer
  var LivePlayer = {
    id: 'livePlayer',

    swfUrl: '//zeus.csslcloud.net/flash/Player.swf',

    isReady: false,

    isPublishing: 0,

    delay: '',

    foreignPublish: '',

    init: function () {
      var flashvars = {
        'userid': DWLive.userid,
        'roomid': DWLive.roomid,
        'foreignPublish': this.foreignPublish,
        'warmvideoid': this.warmVideoId,
        'openhostmode': this.openHostMode, // 多主讲
        'dvr': this.dvr,
        'barrage': this.barrageData,
        'backgroundImageUri': this.backgroundImageUri,
        'backgroundHint': this.backgroundHint,
        'countDownTime': DWLive.liveCountdown,
        'openMultiQuality': DWLive.multiQuality,
        'language': DWLive.language || '',
        'type': 'liveplayer',
        'upid': DWLive.upid,
        'viewerid': this.viewerid,
        'ua': 1
      }

      var buffer = this.delay
      if (buffer > 0) {
        flashvars.buffer = buffer
      }

      var params = {
        allowFullscreen: 'true',
        allowScriptAccess: 'always',
        wmode: 'transparent'
      }
      if (DWLive.isPCH5Live) {
        var opts = {
          roomId: DWLive.roomid,
          userId: DWLive.userid
        }
        if (!Utils.isIE()) {
          var container = document.getElementById('livePlayer')
          $('.flashtip').remove();
          var hdVideoScript = document.createElement('script')
          hdVideoScript.src = '//view.csslcloud.net/js/sdk/3.11.0/hdLivePlayer.js'
          // hdVideoScript.src = './js/hdLivePlayer.js'

          document.body.appendChild(hdVideoScript)
          hdVideoScript.onload = function () {
            if(hdPcLivePlayer.isSuppoted()){
              var playerParams = {roomid: flashvars.roomid,
                userid: flashvars.userid,
                element: container,
                backgroundHint: flashvars.backgroundHint,
                countDownTime: flashvars.countDownTime,
                bacgroundImageUri: flashvars.backgroundImageUri,
                warmVideoId: flashvars.warmvideoid,
                upid: flashvars.upid,
                viewerid: flashvars.viewerid,
                isLowDelay:Utils.isLowDelay(),
                barrage: parseInt(flashvars.barrage,10) == 1,
                isBan: DWLive.isBan,
                sessionid: DWLive.sessionId,
                isShowFullScreen: DWLive.isShowFullScreen,
                isRts: DWLive.viewMode === 1
              }
              // 视频LOGO
              if (DWLive.videoLogo && DWLive.videoLogo.img) {
                playerParams.logoUrl = DWLive.videoLogo.img
                playerParams.logoPosition = DWLive.videoLogo.position
              }
              hdPcLivePlayer.config(playerParams)
              window.UNKNOWSTATUSASKLX = true
              window._swfOk()
              DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('h5')
            }else {
              swfobject.embedSWF(this.swfUrl, this.id, '100%', '100%', '10.0.0',
              '/flash/expressInstall.swf', flashvars, params)
              DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('flash')
            }
          }  
        } else {
          swfobject.embedSWF(this.swfUrl, this.id, '100%', '100%', '10.0.0',
            '/flash/expressInstall.swf', flashvars, params)
          DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('flash')
        }
        //不支持h5pc播放器
        window.hd_h5Live_create_error = function () {
          hdH5LiveVideo = null
          swfobject.embedSWF(this.swfUrl, this.id, '100%', '100%', '10.0.0',
            '/flash/expressInstall.swf', flashvars, params)
          DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('flash')
        }.bind(this)
        window.UNKNOWSTATUSASKLX = false
        if (DWLive.isBan) {
          if (typeof window.on_cc_live_room_ban === 'function') {
            window.on_cc_live_room_ban(this.banReason)
          }
        }

      } else {
        swfobject.embedSWF(this.swfUrl, this.id, '100%', '100%', '10.0.0',
          '/flash/expressInstall.swf', flashvars, params)
        DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('flash')
      }


    },
    getH5player: function () {
      return hdPcLivePlayer.player()
    },
    getFlash: function () {
      // console.log(this.isReady)
      if (!this.isReady || !swfobject || !swfobject.getObjectById) {
        return
      }
      return swfobject.getObjectById(this.id)
    },

    setShowFullScreenBtn: function (e) {
      this.getH5player().setShowFullScreenBtn(e)
    },

    getPlayerTime: function () {
      var t = parseInt((typeof this.getFlash()._time === 'function') ? this.getFlash()._time() : 0)
      if (isNaN(t) || t < 0) {
        return 0
      }
      return t
    },
    isH5Video: function () {
      if (!this.getFlash() && typeof hdPcLivePlayer != 'undefined') {
        return true
      }
      if (typeof hdPcLivePlayer == 'undefined' && this.getFlash()) {
        return false
      }
      return false
    },

    start: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        //禁播
        if (DWLive.isBan) {
          $('#livePlayer').css({
            'text-align': 'center',
            'color': 'white',
            'font-size': '18px',
            'line-height': '232px'
          })
          $('#livePlayer').html('<p>直播已封禁，请联系管理员</p>')
          return
        }

        // setTimeout(function () {
        MobileLive.init()
        // }, DELAY_TIME)
      } else {
        if (this.isH5Video()) {
          if (DWLive.isBan) {
            return
          }
          this.isPublishing = 1
          this.getH5player().startLive()
          return
        }
        if (!this.getFlash()) {
          return
        }
        this.isPublishing = 1
        this.getFlash()._streamStart()
      }
    },

    changeQuality: function (quality, callback) {
      if (this.isH5Video()) {
        this.getH5player().changeStream(quality, callback)
      }
    },
    getQualityIndex: function () {
      if (this.isH5Video()) {
        return this.getH5player().streamIndex
      }
    },

    end: function (j) {
      if (MobileLive.isMobile() == 'isMobile') {
        // setTimeout(function () {
        MobileLive.end(j)
        // }, DELAY_TIME)
      } else {
        if (this.isH5Video() && this.isReady) { // h5player
          if (DWLive.isBan) {
            return
          }
          this.isPublishing = 0
          this.getH5player().endLive(j, 'stu')
          return
        }
        if (!this.getFlash()) {
          return
        }
        this.isPublishing = 0
        this.getFlash()._streamEnd && this.getFlash()._streamEnd()
      }
    },

    // 弹幕
    barrage: function (m) {
      if (!m) {
        return
      }
      if (this.isH5Video()) {  
        this.getH5player().sendBarrage({'type':'text','content':m.txt,'css':{'font':'微软雅黑','size':'14','color': m.color}})
        return
      }

      if (!this.getFlash()) {
        return
      }

      if (this.getFlash()._jsTOASbarrage) {
        this.getFlash()._jsTOASbarrage(m)
      }
    },
    destroy: function () {
      if (MobileLive.isMobile() == 'isMobile') {
        MobileLive.destroy()
      } else {
        if (this.isH5Video() && this.isReady) {
          if (DWLive.isBan) {
            return
          }
          this.isPublishing = 0
          this.getH5player().destroy()
        } else if (this.getFlash()) {
          this.isPublishing = 0
          this.getFlash()._streamEnd && this.getFlash()._streamEnd()
        }
      }
      $('#' + this.id).html('')
    },

    getCurrentLine: function () {
      if (this.isH5Video) {
        return this.getH5player().hostIndex
      }
    },

    getLine: function () {
      if (this.isH5Video()) {
        var l = this.getH5player().lines
        var lineInfo = []
        var t = this
        var len = l.length
        var hIndex = this.getH5player().hostIndex
        for (var i = 0; i < len; i++) {
          var obj = {
            selected: (hIndex == i),
            name: ('线路_' + (i + 1))
          }
          lineInfo.push(obj)
        }
        return lineInfo
      }
      var lines = this.getFlash().getLine ? this.getFlash().getLine() : 0
      if (lines) {
        lines = JSON.parse(lines)
      }
      return lines
    },

    changeLine: function (line) {
      if (this.isH5Video()) {
        return this.getH5player().changeLines(line)
      }
      this.getFlash().changeLine && this.getFlash().changeLine(line)
    },
    changeVideoScale: function (t) {
      this.getFlash()._showScreenScale && this.getFlash()._showScreenScale(t)
    },
    onlyAudio: function () {
      if (this.isH5Video()) {
        return
      }
      this.getFlash()._onlyAudio && this.getFlash()._onlyAudio()
    },
    setSound: function (n) {
      if (this.isH5Video()) {
        // 声音调节方法fix 
        if (this.getH5player().setVolume) {
          return this.getH5player().setVolume(n)
        }
        if (this.getH5player().setSound) {
          return this.getH5player().setSound(n)
        }
      }
      this.getFlash()._SetSound && this.getFlash()._SetSound(n)
    },

    // 打开声音
    openSound: function () {
      if (this.isH5Video()) {
        this.getH5player().setMuted(false)
        return
      }

      if (!this.getFlash()) {
        return
      }

      this.getFlash && this.getFlash()._onSound()
    },

    // 关闭声音
    closeSound: function () {
      if (this.isH5Video()) {
        this.getH5player().setMuted(true)
        return
      }

      if (!this.getFlash()) {
        return
      }

      this.getFlash && this.getFlash()._unSound()
    },

    // 开启关闭弹幕
    openBarrage: function (b) {
      if (this.isH5Video()) {
        return this.getH5player().openBarrage(b)
      }
      if (!this.getFlash()) {
        return
      }

      this.getFlash()._barrage && this.getFlash()._barrage(b)
    },

    showControl: function (b) {
      if (this.isH5Video()) {
        return this.getH5player().showControl(b)
      }
      if (!this.getFlash()) {
        return
      }
      this.getFlash()._ShowControl && this.getFlash()._ShowControl(b)
    },

    switchFullScreen: function (b) {
      if (this.isH5Video()) {
        return this.getH5player().switchFullScreen(b)
      }
      if (!this.getFlash()) {
        return
      }
    },

    //封禁
    banLive: function () {
      DWLive.isBan = true
      if (this.isH5Video()) {
        this.getH5player().banLive()
        return
      }
      if (!this.getFlash()) {
        return
      }
      this.getFlash()._banLive && this.getFlash()._banLive()
    },

    //解禁
    unbanLive: function () {
      DWLive.isBan = false
      if (this.isH5Video()) {
        this.getH5player().unBanLive()
        return
      }
      if (!this.getFlash()) {
        return
      }
      this.getFlash()._unbanLive && this.getFlash()._unbanLive()
    },

    // 显示跑马灯功能
    showMarquee: function (marquee) {
      if (!marquee) {
        return
      }
      if (this.isH5Video()) {
        return this.getH5player().openMarquee(JSON.parse(marquee))
      }
      if (!this.getFlash()) {
        return
      }

      this.getFlash()._showMarqueePlugin && this.getFlash()._showMarqueePlugin(marquee)
    },
    closeMarquee: function () {
      if (this.isH5Video()) {
        return this.getH5player().closeMarquee()
      }
      if (!this.getFlash()) {
        return
      }
      this.getFlash()._closeMarqueePlugin && this.getFlash()._closeMarqueePlugin({ name: 'PluginForMarquee' })
    }
  }

  // window.LivePlayer = LivePlayer;

  window._onStart = function () {
    // console.log('开始推流直播')
  }
  window.cc_callback_onHDReceivedVideoQuality = function (data) {
    DWLive.onHDReceivedVideoQuality && DWLive.onHDReceivedVideoQuality(data)
  }

  function initDrawPanelInfo() {
    if (!isHistoryReady) {
      setTimeout(function () {
        initDrawPanelInfo()
      }, 3000)
      return
    }

    if (DWDpc.fastMode) {
      return
    }

    if (draws.length) {
      DrawPanel.draws(draws)
      draws = []
    }

    // 显示最后一张图片
    if (pageChanges.length) {
      var ppc = pageChanges.pop()
      if (!ppc) {
        return
      }

      DrawPanel.filp(ppc)
      if (animations.length) {
        var animation = animations.pop()

        var animationJ = toJson(animation)
        var ppcJ = toJson(ppc)

        if (ppcJ.docid == animationJ.docid && ppcJ.time <= animationJ.time) {
          DrawPanel.animationFilp(animation)
        }
      }

      pageChanges = []
    }
  }


  // DrawPanel
  var DrawPanel = {
    id: 'drawPanel',

    isReady: false,

    isProcessing: false,

    getWidth: function () {
      return '100%'
    },

    getHeight: function () {
      return '100%'
    },

    swfUrl: '//zeus.csslcloud.net/flash/Player.swf',

    init: function () {
      var flashvars = {
        'type': 'drawpanel'
      }
      var params = {
        allowFullscreen: 'true',
        allowScriptAccess: 'always',
        wmode: 'transparent'
      }
      var attributes = {}

      if (!MobileLive.isIPad() && !MobileLive.isIPhone() && !MobileLive.isAndroid() && !MobileLive.isWindowsPhone()) {
        //开启极速动画模式
        if (!DWDpc.fastMode) {
          swfobject.embedSWF(this.swfUrl, this.id, this.getWidth(), this.getHeight(), '10.0.0', '/flash/expressInstall.swf', flashvars, params, attributes)
        }

      }
    },

    getSwf: function () {
      if (!LivePlayer.isReady) {
        return
      }
      console.log('mark', this.id, swfobject.getObjectById(this.id))
      return swfobject.getObjectById(this.id)
    },

    clear: function () {
      var swf = this.getSwf()
      if (!swf) {
        return
      }
      swf._streamEnd()

      Pusher.pagechangedata = []
      Pusher.drawjson = []
    },

    // 画图
    draw: function (j) {
      var swf = this.getSwf()
      if (!swf) {
        return
      }
      swf.draw(j)
    },

    draws: function (js) {
      var swf = this.getSwf()
      if (!swf) {
        return
      }

      (function (jstr) {
        setTimeout(function () {
          swf.drawList(jstr)
        })
      })(js)
    },

    // 翻页
    filp: function (j) {
      var swf = this.getSwf()
      if (!swf) {
        return
      }

      var documentDisplayMode = DWLive.documentDisplayMode
      if (documentDisplayMode == 1) {
        this.displayMode = 'auto'
      } else if (documentDisplayMode == 2) {
        this.displayMode = 'width'
      } else {
        this.displayMode = 'auto'
      }

      if (live.adapt !== undefined) {
        this.displayMode = live.adapt ? 'auto' : 'width'
      }

      var jj = JSON.parse(j)
      var u = jj.url
      var isHttps = window.location.protocol === 'https:'
      if (isHttps) {
        jj.url = u.replace(/http:/g, 'https:')
      }
      swf.filp(JSON.stringify(jj), this.displayMode)
    },

    // 动画
    animationFilp: function (j) {
      var swf = this.getSwf()
      if (!swf) {
        return
      }

      swf.animation(j)
    },


    // 弹幕
    barrage: function (m) {
      if (!m) {
        return
      }

      if (!this.getSwf()) {
        return
      }

      if (this.getSwf()._jsTOASbarrage) {
        this.getSwf()._jsTOASbarrage(m)
      }
    },

    // 显示跑马灯功能
    showMarquee: function (marquee) {
      if (!marquee) {
        return
      }

      if (!this.getSwf()) {
        return
      }

      this.getSwf().showMarqueeLight(marquee)
    }
  }


  var draws = []
  var pageChanges = []
  var animations = []
  var isHistoryReady = false

  // 历史数据
  var History = function () {
    $.ajax({
      url: '//view.csslcloud.net/api/view/info?userid=' + DWLive.userid + '&roomid=' + DWLive.roomid,
      type: 'GET',
      dataType: 'jsonp',
      success: function (data) {
        if (!data.success) {
          return
        }

        if (!data.datas) {
          return
        }
        var datas = data.datas

        var meta = datas.meta
        if (!meta) {
          return
        }

        LivePlayer.isPublishing = meta.isPublishing

        // 没有推流
        if (meta.isPublishing != 1) {
          return
        }

        if (typeof DWLive.onQuestionnairePublish === 'function') {
          DWLive.onQuestionnairePublish(data)
        }
        if (typeof DWLive.onPracticePublish === 'function') {
          DWLive.onPracticePublish(data)
        }

        var answers = meta.answer ? meta.answer : []
        var questions = meta.question ? meta.question : []
        var broadcasts = meta.broadcast ? meta.broadcast : []
        for (var i = 0; i < answers.length; i++) {
          var answer = answers[i]
          for (var ii = 0; ii < questions.length; ii++) {
            var question = questions[ii]
            if (question.encryptId == answer.encryptId) {
              answer.questionUserId = question.questionUserId
            }
          }
        }

        if (questions && questions.length) {
          for (var i = 0; i < questions.length; i++) {
            var question = questions[i]
            if (typeof DWLive.onQuestion === 'function') {
              DWLive.onQuestion(JSON.stringify({
                'action': 'question',
                'value': {
                  'id': question.encryptId,
                  'content': question.content,
                  'userId': question.questionUserId,
                  'groupId': question.groupId,
                  'userName': question.questionUserName,
                  'isPublish': question.isPublish,
                  'triggerTime': question.triggerTime,
                  'userAvatar': question.questionUserAvatar
                }
              }))
            }
          }
        }

        if (answers && answers.length) {
          for (var i = 0; i < answers.length; i++) {
            var answer = answers[i]
            if (typeof DWLive.onAnswer === 'function') {
              DWLive.onAnswer(JSON.stringify({
                'action': 'answer',
                'value': {
                  'questionId': answer.encryptId,
                  'isPrivate': answer.isPrivate,
                  'content': answer.content,
                  'userId': answer.answerUserId,
                  'groupId': answer.groupId,
                  'userName': answer.answerUserName,
                  'questionUserId': answer.questionUserId,
                  'triggerTime': answer.triggerTime,
                  'userAvatar': answer.userAvatar
                }
              }))
            }
          }
        }

        if (broadcasts && broadcasts.length) {
          for (var i = 0; i < broadcasts.length; i++) {
            var broadcast = broadcasts[i]
            if (typeof DWLive.onBroadcastMsg == 'function') {
              DWLive.onBroadcastMsg({
                content: broadcast.content,
                time: broadcast.time,
                id: broadcast.id
              })
            }
          }
        }

        if (MobileLive.isMobile() == 'isMobile' && $.DrawingBoard) {
          $.DrawingBoard.history(meta)
        }

        //极速动画获取历史信息
        DWDpc.history(meta)

        var chatLogs = meta.chatLog
        if (chatLogs && chatLogs.length) {
          var cls = []
          for (var i = 0; i < chatLogs.length; i++) {
            var chatLog = chatLogs[i]


            cls.push({
              'userid': chatLog.userId,
              'username': chatLog.userName,
              'userrole': chatLog.userRole,
              'useravatar': chatLog.userAvatar,
              'groupId': chatLog.groupId,
              'msg': chatLog.content,
              'time': chatLog.time,
              'chatId': chatLog.chatId,
              'status': chatLog.status,
              'usercustommark': chatLog.userCustomMark
            })
          }

          if (DWLive.onPublicChatMessage && typeof DWLive.onPublicChatMessage === 'function') {
            for (var idx = 0; idx < cls.length; idx++) {
              DWLive.onPublicChatMessage(JSON.stringify(cls[idx]))
            }
          }
        }

        if (!DWDpc.fastMode) {
          var pageChange = meta.pageChange
          if (pageChange && pageChange.length) {
            pageChange.sort(function (p1, p2) {
              return parseInt(p1.time) - parseInt(p2.time)
            })
            var lastPage = pageChange.pop()
            pageChanges.push(JSON.stringify({
              'fileName': lastPage.docName,
              'totalPage': lastPage.docTotalPage,
              'docid': lastPage.encryptDocId,
              'url': lastPage.url,
              'page': lastPage.pageNum,
              'time': lastPage.time,
              'useSDK': lastPage.useSDK
            }))
          }

          var animation = meta.animation
          if (animation && animation.length) {
            animation.sort(function (p1, p2) {
              return parseInt(p1.time) - parseInt(p2.time)
            })
            var lastAnimation = animation.pop()
            animations.push(JSON.stringify({
              'fileName': lastAnimation.docName,
              'totalPage': lastAnimation.docTotalPage,
              'docid': lastAnimation.encryptDocId,
              'url': lastAnimation.url,
              'page': lastAnimation.pageNum,
              'time': lastAnimation.time,
              'step': lastAnimation.step
            }))
          }

          var draw = meta.draw
          if (draw && draw.length) {
            for (var i = 0; i < draw.length; i++) {
              draws.push(draw[i].data)
            }
          }
        }

        isHistoryReady = true
      }
    })
  }


  var opts = {
    // 互动信息
    interaction: {
      id: 'interactionPlayer',
      width: '100%',
      height: '100%'
    }
  }
  var Live = function (opts) {
    this.interaction = new Interaction(opts)
  }
  var live = new Live(opts)
  window.live = live

  window.on_drampanel_ready = function () {
    // 画板Flash加载完成回调
    DrawPanel.isReady = true
    setTimeout(function () {
      initDrawPanelInfo()
    }, 1500)
  }


  // 画图事件
  window.on_cc_live_dw_draw = function (data) {
    setTimeout(function () {
      DWDpc.draw(data)
    }, getDeltaTime())
    setTimeout(function () {
      var j = toJson(data)
      DrawPanel.draw(JSON.stringify(j.value.data))
    }, getDeltaTime())
    if (MobileLive.isMobile() == 'isMobile') {
      setTimeout(function () {
        $.DrawingBoard && $.DrawingBoard.db(data)
      }, getDeltaTime())
    }
  }

  // 翻页事件
  window.on_cc_live_dw_page_change = function (data) {
    //极速动画
    setTimeout(function () {
      DWDpc.pageChange(data)
    }, getDeltaTime())
    //flash
    setTimeout(function () {
      var j = toJson(data)
      DrawPanel.filp(JSON.stringify(j.value))
    }, getDeltaTime())
    //canvas
    if (MobileLive.isMobile() == 'isMobile') {
      setTimeout(function () {
        $.DrawingBoard && $.DrawingBoard.db(data)
      }, getDeltaTime())
    }
  }

  // 动画翻页事件
  window.on_cc_live_dw_animation_change = function (data) {
    setTimeout(function () {
      DWDpc.animationChange(data)
    }, getDeltaTime())
    setTimeout(function () {
      var j = toJson(data)
      DrawPanel.animationFilp(JSON.stringify(j.value))
    }, getDeltaTime())
    if (MobileLive.isMobile() == 'isMobile') {
      setTimeout(function () {
        $.DrawingBoard && $.DrawingBoard.db(data)
      }, getDeltaTime())
    }
  }

 // dp postMessage通信处理 
  window.messageFromDp = function (data) {
    var action = data.action
    var detail = {
      userId: DWLive.viewerid,
      userName: DWLive.viewername,
      docMsg: data.page
    }
    if (action === 'dpImageLoadError') { // 静态文档翻页失败
      ccTrackLog.pageChangeFailed(data.page)
      // console.log('dpImageLoadError', detail)
      if (typeof window.on_cc_live_pagechange_error === 'function') {
        window.on_cc_live_pagechange_error(detail)
      }
    }
    if (action === 'dpImageLoadComplete') {  // 静态文档翻页成功
      // console.log('dpImageLoadComplete', detail)
      if (typeof window.on_cc_live_pagechange_complete === 'function') {
        DWLive.docInfo =  {
          docId: data.page.docId,
          pageNum: data.page.pageNum
        }
        window.on_cc_live_pagechange_complete(detail)
      }
    }
  }

  if (window.addEventListener) {
    window.addEventListener('message', function (event) {
      messageFromDp(toJson(event.data))
    })
  } else {
    window.attachEvent('onmessage', function (event) {
      messageFromDp(toJson(event.data))
    })
  }


  // Chat
  var Chat = {
    init: function () {
      Pusher.socket.on('chat_message', function (j) {
        if (DWLive.onPublicChatMessage && typeof DWLive.onPublicChatMessage === 'function') {
          DWLive.onPublicChatMessage(j, 'live')
        }
      })
      //聊天审核
      Pusher.socket.on('chat_log_manage', function (j) {
        if (typeof DWLive.onPublicChatLogManage === 'function') {
          console.log('onPublicChatLogManage', j)
          DWLive.onPublicChatLogManage(j)
        }
      })

      // 消息提醒
      Pusher.socket.on('notification', function (j) {
        if (typeof DWLive.onNotification === 'function') {
          DWLive.onNotification(j)
        }
      })

      Pusher.socket.on('information', function (j) {
        if (typeof DWLive.onInformation === 'function') {
          console.log('onInformation', j)
          DWLive.onInformation(j)
        }
      })

      // 接收发送私聊函数
      Pusher.socket.on('private_chat_self', function (j) {
        if (typeof DWLive.onPrivateChatMessage === 'function') {
          console.log('onPrivateChatMessage', j)
          DWLive.onPrivateChatMessage(j)
        }
      })

      // 接收回答私聊函数
      Pusher.socket.on('private_chat', function (j) {
        if (typeof DWLive.onPrivateAnswer === 'function') {
          console.log('onPrivateAnswer', j)
          DWLive.onPrivateAnswer(j)
        }
      })

      // 在线列表
      Pusher.socket.on('room_context', function (msg) {

      })

      // 自定义消息
      Pusher.socket.on('custom_message', function (j) {
        if (typeof DWLive.onCustomChatMessage === 'function') {
          DWLive.onCustomChatMessage(j)
        }
      })
    }
  }

  // Qa
  var Qa = {
    init: function () {

      // 问答->提交问题
      Pusher.socket.on('question', function (j) {
        if (typeof DWLive.onQuestion === 'function') {
          console.log('onQuestion', j)
          DWLive.onQuestion(j)
        }
        if (typeof DWLive.onQuestionSend === 'function') {
          DWLive.onQuestionSend(j)
        }
      })

      // 问答->返回答案
      Pusher.socket.on('answer', function (j) {
        if (typeof DWLive.onAnswer === 'function') {
          console.log('onAnswer', j)
          DWLive.onAnswer(j)
        }
        if (typeof DWLive.onAnswerSend === 'function') {
          DWLive.onAnswerSend(j)
        }
      })
    }
  }

  //事件兼容处理
  var Event = {}
  Event.addEvents = function (target, eventType, handle) {
    if (document.addEventListener) {
      Event.addEvents = function (target, eventType, handle) {
        target.addEventListener(eventType, handle, false)
      }
    } else {
      Event.addEvents = function (target, eventType, handle) {
        target.attachEvent('on' + eventType, function () {
          handle.call(target, arguments)
        })
      }
    }

    Event.addEvents(target, eventType, handle)
  }

  
  var ajaxGET = function (uri, params, callback) {
    var url  = '//view.csslcloud.net' + uri
    $.ajax({
      url: url,
      type: 'GET',
      dataType: 'json',
      data: params,
      headers:{ 'X-HD-Token': DWLive.sessionId},
      success: function (data) {
        callback && callback(data)
      },
      error: function (error) {
        console.log('error', uri, error)
      }
    })
  }
  var ajaxPOST = function (uri, params, callback) {
    var url  = '//view.csslcloud.net' + uri
    $.ajax({
      url: url,
      headers:{ 
        'X-HD-Token': DWLive.sessionId,
        'Content-Type': 'application/json'
      },
      data: JSON.stringify(params),
      type: 'POST',
      dataType: 'json',
      success: function (data) {
        callback && callback(data)
      },
      error: function (error) {
        callback && callback(error)
        console.log(error)
      }
    })
  }

  var callbackMsg = {
    STREAM_ERROR: {
      code: 404,
      msg: '清晰度不存在～'
    },
    LINE_ERROR: {
      code: 404,
      msg: '线路不存在～'
    },
    SWITCH_ERROR: {
      code: 500,
      msg: '切换失败，请重试～'
    },
    STREAM_SUCCESS: {
      code: 200,
      msg: '切换成功～'
    },
    LINE_SUCCESS:  {
      code: 200,
      msg: '切换成功～'
    }
  }
  var PLAY_EVENT = {
    CANPLAY: "canplay",
    WAITING: "waiting",
    PLAYING: "playing",
    MEDIA: 'media'
  }

  var MobileLive = {
    src: '',
    audio: false,
    line: 0,
    controls: true,
    baseURL: '//view.csslcloud.net',
    isRtsStream: false,
    waitingTimer: -1,
    catonNum: 0,
    isIosUc: !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) && navigator.userAgent.indexOf('UCBrowser') > -1, // ios uc 浏览器播放不了 rts 降级处理
    addStyle: function () {
      var videoStyle = document.createElement("style");
      var styleSheet = `.ccplayer-loading-icon {width:120px;height:40px;text-align:center;line-height:40px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);}
      .ccplayer-loading-icon .ccplayer-loading-dot{-webkit-animation: ccplayer-loading-dot-fade .8s ease infinite;animation: ccplayer-loading-dot-fade .8s ease infinite;opacity: 0;transform-origin: 4px 4px}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-7 {-webkit-animation-delay: .7s;animation-delay: .7s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-6 {-webkit-animation-delay: .6s;animation-delay: .6s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-5 {-webkit-animation-delay: .5s;animation-delay: .5s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-4 {-webkit-animation-delay: .4s;animation-delay: .4s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-3 {-webkit-animation-delay: .3s;animation-delay: .3s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-2 {-webkit-animation-delay: .2s;animation-delay: .2s}
      .ccplayer-loading-icon .ccplayer-loading-dot.ccplayer-loading-dot-1 {-webkit-animation-delay: .1s;animation-delay: .1s}
      @-webkit-keyframes ccplayer-loading-dot-fade {
        0% {opacity: .7;transform: scale(1.2)}
        50% {opacity: .25;transform: scale(.9)}
        to {opacity: .25;transform: scale(.85)}
      }
      @keyframes ccplayer-loading-dot-fade {
        0% {opacity: .7;transform: scale(1.2)}
        50% {opacity: .25;transform: scale(.9)}
        to {opacity: .25;transform: scale(.85)}
      }`
      try{
        videoStyle.appendChild(document.createTextNode(styleSheet));
      }catch(err){
        videoStyle.styleSheet.cssText = styleSheet;//针对IE
      }
      var head = document.getElementsByTagName("head")[0];
      head.appendChild(videoStyle);
    },
    init: function () {
      var _this = this
      if (DWLive.isBan) {
        $('#livePlayer').css({
          'text-align': 'center',
          'color': 'white',
          'font-size': '18px',
          'line-height': '232px'
        })
        $('#livePlayer').html('<p>直播已封禁，请联系管理员</p>')
        return
      }     
      var logoUrl = ''
      var logoPositionStyle = ''
      this.addStyle()
      if (DWLive.videoLogo && DWLive.videoLogo.img) {
          logoUrl = DWLive.videoLogo.img
          switch (DWLive.videoLogo.position) {
            case 1:
              logoPositionStyle = 'display: block; font-size: 0; top: 0; right: 0;'
              break;
            case 2:
              logoPositionStyle = 'display: block; font-size: 0; bottom: 0; right: 0;'
              break;
            case 3:
              logoPositionStyle = 'display: block; font-size: 0; top: 0; left: 0;'
              break;
            case 4:
              logoPositionStyle = 'display: block; font-size: 0; bottom: 0; left: 0;'
              break;
            default:
              logoPositionStyle = 'display: block; font-size: 0; top: 0; right: 0;'
              break;
          }
      }
      ajaxGET('/api/live/record', 
        {accountId: DWLive.userid, roomId: DWLive.roomid, sessionId: DWLive.sessionId},
        function (data) {
          if (data.success && data.data.live.status === 1) { // 直播ing
            options.init()
            var videoDom
            var waitingDom = '<span class="ccplayer-loading-icon"><svg style="width:100%;height:100%" version="1.1" viewBox="0 0 22 22"><svg x="7" y="1"><circle class="ccplayer-loading-dot ccplayer-loading-dot-0" cx="4" cy="4" r="2"></circle></svg><svg x="11" y="3"><circle class="ccplayer-loading-dot ccplayer-loading-dot-1" cx="4" cy="4" r="2"></circle></svg><svg x="13" y="7"><circle class="ccplayer-loading-dot ccplayer-loading-dot-2" cx="4" cy="4" r="2"></circle></svg><svg x="11" y="11"><circle class="ccplayer-loading-dot ccplayer-loading-dot-3" cx="4" cy="4" r="2"></circle></svg><svg x="7" y="13"><circle class="ccplayer-loading-dot ccplayer-loading-dot-4" cx="4" cy="4" r="2"></circle></svg><svg x="3" y="11"><circle class="ccplayer-loading-dot ccplayer-loading-dot-5" cx="4" cy="4" r="2"></circle></svg><svg x="1" y="7"><circle class="ccplayer-loading-dot ccplayer-loading-dot-6" cx="4" cy="4" r="2"></circle></svg><svg x="3" y="3"><circle class="ccplayer-loading-dot ccplayer-loading-dot-7" cx="4" cy="4" r="2"></circle></svg></svg></span>'
            if (_this.controls) {
              videoDom = '<div id="marquee" style="width: 100%;height: 100%;position: absolute;overflow:hidden;left: 0px;top: 0px;pointer-events: none;z-index:20"></div><div id="videoLoading" style="display:none; color:#fff; width:100%;height:100%;justify-content: center;align-items: center;font-size:14px;position: absolute;z-index: 10;">' + waitingDom + '</div><div id="videoWaiting" style="display:none; color:#fff;width:100%;height:100%;justify-content: center;align-items: center;font-size:14px;position: absolute;z-index: 10;">当前网络质量不佳，正在切换线路...</div><video id="player_live" style="display: none; z-index: 1; position: absolute; left: 0" webkit-playsinline x5-video-player-type="h5-page" playsinline controls autoplay x-webkit-airplay="allow" x5-playsinline width="100%" height="100%" ></video><div style="display:none;  z-index: 2; position:absolute;width:20%;'+logoPositionStyle+'" id="ccVideoLogo" class="cc-video-logo"><img style="width: 100%; display: block;" src='+logoUrl+' /></div>'
            } else {
              videoDom = '<div id="marquee" style="width: 100%;height: 100%;position: absolute;overflow:hidden;left: 0px;top: 0px;pointer-events: none;z-index:20"></div><div id="videoLoading" style="display:none; color:#fff;width:100%;height:100%;justify-content: center;align-items: center;font-size:14px;position: absolute;z-index: 10;">' + waitingDom + '</div><div id="videoWaiting" style="display:none; color:#fff;width:100%;height:100%;justify-content: center;align-items: center;font-size:14px;position: absolute;z-index: 10;">当前网络质量不佳，正在切换线路...</div><video id="player_live" style="display: none; z-index: 1; position: absolute; left: 0" webkit-playsinline x5-video-player-type="h5-page" playsinline autoplay x-webkit-airplay="allow" x5-playsinline width="100%" height="100%"></video><div style="display:none; z-index: 2; position:absolute;width:20%;'+logoPositionStyle+'" id="ccVideoLogo" class="cc-video-logo"><img style="width: 100%;display: block;" src='+logoUrl+' /></div>'
            }
            $('#' + LivePlayer.id).html(videoDom)
            $('#' + LivePlayer.id).css({'position': 'relative', 'overflow': 'hidden'})
            _this.video = document.getElementById('player_live')

            if ((DWLive.rtsFlag || DWLive.viewMode === 1) && !_this.isIosUc) { // 是否开启rts低延时模式
              const aliRts = AliRTS.createClient()
              aliRts.isSupport({
                isReceiveVideo: true
              }).then(() => {
                _this.getRTSHosts()
              }).catch(() => {
                _this.getH5PlayerHosts()
              })
            } else { 
              _this.getH5PlayerHosts()
            }
          } else { //未直播
            $('#livePlayer').css({
              'text-align': 'center',
              'color': 'white',
              'font-size': '18px',
              'line-height': '232px'
          })
          $('#livePlayer').html('<p>直播等待中</p>')
        }
      })
    },
    // 获取直播地址
    setPlayUrl () {
      var _this = this

      if ((DWLive.rtsFlag || DWLive.viewMode === 1) && !_this.isIosUc) {
        this.aliRts && this.rtsPlayerDestroyed()
        this.aliRts = null
        this.isRtsStream = false

      ajaxGET('/api/live/play', {accountId: DWLive.userid, roomId: DWLive.roomid, sessionId: DWLive.sessionId, types: 'rts', platform: 1, terminal: 1}, function (data) {
          if (data.success && data.data.stream.length > 0) {
            if (data.data.stream[0].docDelayTime && window.cc_doc_delaytime) {
              window.cc_doc_delaytime(data.data.stream[0].docDelayTime)
            }
            _this.rtsStreams = data.data.stream[0]
            _this.rtsVideoLine = _this.rtsStreams.videos[0].videoStream[0]
            _this.currentLines = _this.rtsStreams.videos[0].videoStream
            _this.rtsAudioLine = _this.rtsStreams.audios[0]
            _this.currentLineIndex = 0
            _this.currentQualityCode = _this.rtsStreams.videos[0].quality
  
            var currentUrl = _this.rtsVideoLine
            // 音频模式
            if (MobileLive.audio) {
              currentUrl = _this.rtsAudioLine + '@subvideo=no'
            }
           
            _this.aliRts = AliRTS.createClient()
            _this.aliRts.isSupport({
              isReceiveVideo: true
            }).then(() => {
              _this.bindRTSEvent()
              DWLive.onLiveStarting && DWLive.onLiveStarting()
              _this.isRtsStream = true
              _this.aliRts.subscribe(currentUrl, {
                mediaTimeout: 5000 // 自定义超时事件的触发时间
              }).then(remoteStream => {
                remoteStream.play(_this.video)
                $('#livePlayer .video-big-playBtn').hide()
              }).catch(err => {// 不支持rts低延时
                console.log('rts订阅失败：subscribe error', err);
              })
            }).catch(() => {
              _this.getH5PlayerHosts()
            })
  
            var videoQuality = JSON.parse(JSON.stringify(_this.rtsStreams.videos)).map((item) => {
              delete item.videoStream 
              return item
            })
            DWLive.onHDReceivedVideoQuality && DWLive.onHDReceivedVideoQuality(videoQuality)
          }
        })
      } else {
        ajaxGET('/api/live/play', {accountId: DWLive.userid, roomId: DWLive.roomid, sessionId: DWLive.sessionId, types: 'hls', platform: 1, terminal: 1, tpl: DWLive.tpl}, function (data) {
          if (data.success && data.data.stream.length > 0) {
            if (data.data.stream[0].docDelayTime && window.cc_doc_delaytime) {
              window.cc_doc_delaytime(data.data.stream[0].docDelayTime)
            }
            _this.videoStreams = data.data.stream[0].videos
            _this.audioStreams = data.data.stream[0].audios
            _this.currentQualityStream = _this.videoStreams[0]          // 当前清晰度
            _this.currentQualityCode = _this.videoStreams[0].quality    // 当前清晰度code
            _this.currentLines = _this.currentQualityStream.videoStream // 当前线路索引
            _this.currentLineIndex = 0                                  // 当前线路
            _this.currentLine = _this.currentLines[0]
  
            // 音频模式
            if (MobileLive.audio) {
              _this.currentLine = _this.audioStreams[_this.currentLineIndex]
            }
            _this.initPlayer()
            var videoQuality = JSON.parse(JSON.stringify(_this.videoStreams)).map((item) => {
              delete item.videoStream 
              return item
            })
            DWLive.onHDReceivedVideoQuality && DWLive.onHDReceivedVideoQuality(videoQuality)
          }
        })
      }
    },
    getH5PlayerHosts: function () {
      var _this = this
      ajaxGET('/api/live/play', {accountId: DWLive.userid, roomId: DWLive.roomid, sessionId: DWLive.sessionId, types: 'hls', platform: 1, terminal: 1},
      function (data) {
        if (data.success && data.data.stream.length > 0) {
          if (data.data.stream[0].docDelayTime && window.cc_doc_delaytime) {
            window.cc_doc_delaytime(data.data.stream[0].docDelayTime)
          }
          _this.videoStreams = data.data.stream[0].videos
          _this.audioStreams = data.data.stream[0].audios
          _this.currentQualityStream = _this.videoStreams[0]          // 当前清晰度
          _this.currentQualityCode = _this.videoStreams[0].quality    // 当前清晰度code
          _this.currentLines = _this.currentQualityStream.videoStream // 当前线路索引
          _this.currentLineIndex = 0                                  // 当前线路
          _this.currentLine = _this.currentLines[0]
          _this.initPlayer()
          var videoQuality = JSON.parse(JSON.stringify(_this.videoStreams)).map(function (item){
            delete item.videoStream 
            return item
          })
          DWLive.onHDReceivedVideoQuality && DWLive.onHDReceivedVideoQuality(videoQuality)
        }
      })
    },
    getRTSHosts: function () {
      var _this = this
      ajaxGET('/api/live/play', {accountId: DWLive.userid, roomId: DWLive.roomid, sessionId: DWLive.sessionId, types: 'rts', platform: 1, terminal: 1},
      function (data) {
        if (data.success && data.data.stream.length > 0) {
          if (data.data.stream[0].docDelayTime && window.cc_doc_delaytime) {
            window.cc_doc_delaytime(data.data.stream[0].docDelayTime)
          }
          _this.rtsStreams = data.data.stream[0]
          _this.rtsVideoLine = _this.rtsStreams.videos[0].videoStream[0]
          _this.currentLines = _this.rtsStreams.videos[0].videoStream
          _this.rtsAudioLine = _this.rtsStreams.audios[0]
          _this.currentLineIndex = 0
          _this.currentQualityCode = _this.rtsStreams.videos[0].quality
          _this.initRtsPlayer()
          var videoQuality = JSON.parse(JSON.stringify(_this.rtsStreams.videos)).map(function(item){
            delete item.videoStream 
            return item
          })
          DWLive.onHDReceivedVideoQuality && DWLive.onHDReceivedVideoQuality(videoQuality)
        }
      })
    },
    initRtsPlayer: function () {
      var _this  = this
      DWLive.onLiveStarting && DWLive.onLiveStarting()
      _this.isRtsStream = true
      var waitingDom = '<span class="ccplayer-loading-icon"><svg style="width:100%;height:100%" version="1.1" viewBox="0 0 22 22"><svg x="7" y="1"><circle class="ccplayer-loading-dot ccplayer-loading-dot-0" cx="4" cy="4" r="2"></circle></svg><svg x="11" y="3"><circle class="ccplayer-loading-dot ccplayer-loading-dot-1" cx="4" cy="4" r="2"></circle></svg><svg x="13" y="7"><circle class="ccplayer-loading-dot ccplayer-loading-dot-2" cx="4" cy="4" r="2"></circle></svg><svg x="11" y="11"><circle class="ccplayer-loading-dot ccplayer-loading-dot-3" cx="4" cy="4" r="2"></circle></svg><svg x="7" y="13"><circle class="ccplayer-loading-dot ccplayer-loading-dot-4" cx="4" cy="4" r="2"></circle></svg><svg x="3" y="11"><circle class="ccplayer-loading-dot ccplayer-loading-dot-5" cx="4" cy="4" r="2"></circle></svg><svg x="1" y="7"><circle class="ccplayer-loading-dot ccplayer-loading-dot-6" cx="4" cy="4" r="2"></circle></svg><svg x="3" y="3"><circle class="ccplayer-loading-dot ccplayer-loading-dot-7" cx="4" cy="4" r="2"></circle></svg></svg></span>'
      var maskDom = '<div class="video-big-playBtn" style="position:relative;display:flex; justify-content: center; align-items: center; width: 100%; height:100%; background: rgba(0,0,0,.6);z-index: 3;"><div id="rtsPlayBtn" style="width: 60px; height: 60px; background: url(//view.csslcloud.net/images/big-play-btn.png) no-repeat; background-size: 60px"></div><div id="videoLoading" style="display:none; color:#fff;">' + waitingDom + '</div><div id="videoWaiting" style="display:none; color:#fff;">当前网络质量不佳，正在切换线路...</div></div>'
      $('#livePlayer').append(maskDom)
      
      _this.rtsPlayerDestroyed()
      _this.aliRts = AliRTS.createClient()
      _this.bindRTSEvent()
      _this.subscribeRts(_this.rtsVideoLine)

      $('#rtsPlayBtn').on('click', function () {
        $('#videoLoading').css('display', 'flex')
        _this.play()
        $('#player_live')[0].play()
        $('#livePlayer .video-big-playBtn').hide()
      })
    },
    subscribeRts: function (rtsLineUrl, type) {
      var _this = this
      $('#player_live').show()
      _this.aliRts.subscribe(rtsLineUrl, {
        mediaTimeout: 5000 // 自定义超时事件的触发时间
      }).then(remoteStream => {
        remoteStream.play(_this.video)
        if (type && type === 'replay') {
          $('#livePlayer .video-big-playBtn').hide()
        }
      }).catch(err => {// 不支持rts低延时
        console.log('rts订阅失败：subscribe error', err)
      })
    },
    bindRTSEvent: function () {
      var _this  = this
      _this.aliRts.on("onError", function(err) {
        _this.catonNum = _this.catonNum + 1
        window.cc_player_stream_disconnect && window.cc_player_stream_disconnect()
        if (err.errorCode === 10201) { // 静音播放
          window.rtsPlayOnError && window.rtsPlayOnError()
        }
        ccTrackLog && ccTrackLog.playError(err)
      })
      _this.aliRts.on('onPlayEvent', function(play){
        if (play.event === PLAY_EVENT.MEDIA) {
          $('#videoLoading').css('display', 'none')
        } else if(play.event === PLAY_EVENT.CANPLAY){
          _this.catonNum = 0
          // console.log('rts canplay')
          $('#videoLoading').css('display', 'none')
          $('#videoWaiting').css('display', 'none')
          //拉流可以播放
        } else if (play.event === PLAY_EVENT.WAITING){
          _this.catonNum = _this.catonNum + 1
          window.cc_player_stream_waiting && window.cc_player_stream_waiting()
          $('#videoWaiting').css('display', 'flex')
          // console.log('rts waiting')

          // 播放重试
          if (_this.waitingTimer !== -1) {
            clearTimeout(_this.waitingTimer)
            _this.waitingTimer = -1
          }
          _this.waitingTimer = setTimeout(function () {
            _this.rtsReplay()
            // console.log('触发播放重试')
          }, 5000)

          //拉流卡顿等待缓冲中 （仅Chrome）
        } else if (play.event === PLAY_EVENT.PLAYING){
          // console.log('rts play')
          $('#videoLoading').css('display', 'none')
          $('#videoWaiting').css('display', 'none')
          //拉流卡顿结束恢复播放 （仅Chrome）
        }
      })
    },
    getLine: function () {
      return this.currentLines
    },
    getCurrentLine: function () {
      return this.currentLineIndex
    },
    initPlayer: function () {
      $('#player_live').show()
      this.video.src = this.currentLine
      ccTrackLog.setUrl(this.currentLine)
      ccTrackLog.bindVideoEvent(this.video)
      DWLive.onLiveStarting && DWLive.onLiveStarting()
      DWLive.on_hd_live_player_type && DWLive.on_hd_live_player_type('h5')
      DWLive.onPlayerLoad && DWLive.onPlayerLoad(this.video)
      DWLive.onKickOutMobile = function () {
        $('#' + LivePlayer.id).html('')
      }
      if (this.report) return
      this.report = new ReportLog(options, 1, 11, this.video, true)
    },
    showControl: function (b) {
      this.controls = b
      this.video.controls = b
    },
    switchFullScreen: function (b) {
      var el = $('#player_live')[0]
      if(b){
        if (el.requestFullscreen) {
          el.requestFullscreen();
        } else if (el.mozRequestFullScreen) {
          el.mozRequestFullScreen();
        }  else if(el.msRequestFullscreen){
          el.msRequestFullscreen(); 
        } else if (el.webkitSupportsFullscreen) {
          el.webkitEnterFullscreen();
        }
      }else{
        if (el.exitFullscreen) {
          el.exitFullscreen();
        } else if (el.msExitFullscreen) {
          el.msExitFullscreen();
        } else if (el.mozExitFullScreen) {
          el.mozExitFullScreen();
        } else if (el.webkitExitFullscreen) {
          el.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        }
      }
    },
    ban: function () {
      $('#livePlayer').css({
        'text-align': 'center',
        'color': 'white',
        'font-size': '18px',
        'line-height': '232px'
      })
      ccTrackLog.endLive()
      $('#livePlayer').html('<p>直播已封禁，请联系管理员</p>')
    },
    unban: function () {
      $('#livePlayer').css({
        'text-align': '',
        'color': '',
        'font-size': '',
        'line-height': ''
      })
      this.init()
    },
    destroy: function () {
      if (this.isRtsStream) {
        this.rtsPlayerDestroyed()
      } else {
        this.video.pause()
        this.video.removeAttribute('src')
        this.video.load()
      }
      if (ccTrackLog.ccTrackTimer) {
        clearInterval(ccTrackLog.ccTrackTimer)
        ccTrackLog.ccTrackTimer = null
      }
    },
    end: function (j) {
      if (this.isRtsStream) {
        this.rtsPlayerDestroyed();
      }
      $('#livePlayer').css({
        'text-align': 'center',
        'color': 'white',
        'font-size': '18px',
        'line-height': '232px'
      })
      ccTrackLog.endLive()
      j = JSON.parse(j)
      if (j && j.msg && j.msg.tips && j.msg.tips.pool && j.msg.tips.pool[j.msg.tips.stu]) {
        // 违规了 涉黄或暴恐涉政
        $('#livePlayer').html(j.msg.tips.pool[j.msg.tips.stu])
      } else {
        $('#livePlayer').html('直播已结束')
      }
    },
    appendDoc: function (s) {
      var isHttps = window.location.protocol === 'https:'
      if (isHttps) {
        s = s.replace(/http:/g, 'https:')
      }
      var img = '<img src="' + s + '" />'
      $('#' + DrawPanel.id).html(img)
    },
    changeQuality: function (quality, callback) {
      ccTrackLog.videoWaitingTotalCount = 0 // waiting总计数重置为0
      var _this = this
      if (this.isRtsStream) return
      if (MobileLive.audio) return
      if (!this.videoStreams.find(function(item){return item.quality === quality})){
        callback && callback(callbackMsg.STREAM_ERROR)
        return
      }
      this.currentQualityCode = quality
      this.currentQualityStream = this.videoStreams.find(function(item) {
        return item.quality === _this.currentQualityCode
      })
      if (this.currentQualityStream && this.currentQualityStream.videoStream) {
        this.currentLines = this.currentQualityStream.videoStream
      }
      if (this.currentLines && !this.currentLines[this.currentLineIndex]) {
        this.currentLineIndex = 0
      }
      try {
        this.currentLine = this.currentLines[this.currentLineIndex]
        ccTrackLog.setUrl(this.currentLine)
        $('#' + LivePlayer.id).find('video').attr('src', this.currentLine)
        callback && callback(callbackMsg.STREAM_SUCCESS)
      } catch (error) {
        callback && callback(callbackMsg.SWITCH_ERROR)
      }
    },
    getQualityIndex: function () {
      if (this.isRtsStream) return
      return this.currentQualityCode
    },
    changeLine: function (line, callBack) {
      ccTrackLog.videoWaitingTotalCount = 0 // waiting总计数重置为0
      if (this.isRtsStream) return
      if (MobileLive.audio) {
        if (!this.audioStreams[line]) {
          return callBack && callBack(callbackMsg.LINE_ERROR)
        }
        audio.src = ''
        audio.src = this.audioStreams[line]
        audio.play()
      } else {
        if (!this.currentLines[line]) {
          return callBack && callBack(callbackMsg.LINE_ERROR)
        }
        this.currentLine = this.currentLines[line]
        ccTrackLog.setUrl(this.currentLine)
        $('#' + LivePlayer.id).find('video').attr('src', this.currentLine)
      }
      callBack && callBack(callbackMsg.LINE_SUCCESS)
      this.currentLineIndex = line
    },
    rtsPlayerDestroyed: function () {
      if (!this.aliRts) return
      this.aliRts.unsubscribe();
      this.aliRts = null;
    },
    play: function () {
      this.video.play()
    },
    rtsReplay: function () {
      var _this = this
      if (MobileLive.audio) { // 音频
        this.aliRts.unsubscribe()
        _this.aliRts.isSupport({
          isReceiveVideo: false
        }).then(() => {
          _this.bindRTSEvent()
          _this.subscribeRts(_this.rtsAudioLine + '@subvideo=no', 'replay')
        }).catch(() => {
          _this.getH5PlayerHosts()
          console.error('浏览器不支持RTS音频播放')
        })
      } else {
        this.aliRts.unsubscribe()
        _this.aliRts.isSupport({
          isReceiveVideo: true
        }).then(() => {
          _this.bindRTSEvent()
          _this.subscribeRts(_this.rtsVideoLine, 'replay')
        }).catch(() => {
          _this.getH5PlayerHosts()
          console.error('浏览器不支持RTS音频播放')
        })
      }
    },
    onlyAudio: function () {
      var v = $('#' + LivePlayer.id).find('video')
      this.video = document.getElementById('player_live')
      v.show()
      MobileLive.audio = !MobileLive.audio
      if (this.isRtsStream && !MobileLive.isIosUc) {
        this.rtsReplay()
      } else {
        if (MobileLive.audio) { // 音频
          audio = new Audio()
          audio.src = this.audioStreams[this.currentLineIndex]
          audio.play()
        } else {
          audio.src = ''
          v.attr('src', this.currentLines[this.currentLineIndex])
          v.play()
        }
      }
    },
    setMuted: function (muted) {
      if (this.isRtsStream) {
        this.video.volume = muted ? 0 : 1
        // this.aliRts.muteLiveStream(muted)
      } else {
        if (this.video) {
          this.video.muted = muted
        }
      }
    },
    isMobile: function () {
      if (this.isIPad() || this.isIPhone() || this.isAndroid() || this.isWindowsPhone()) {
        return 'isMobile'
      }
    },
    isIPad: function () {
      return navigator.userAgent.match(/iPad/i) != null
    },
    isIPhone: function () {
      return navigator.userAgent.match(/iPhone/i) != null
    },
    isAndroid: function () {
      return navigator.userAgent.match(/Android/i) != null
    },
    isWindowsPhone: function () {
      return navigator.userAgent.match(/Windows Phone/i) != null
    },
    showMarquee: function (m) {
      if (!m) return
      if (!this.marquee) {
        this.loadMarqueePlugin('//image.csslcloud.net/js/marquee.js', m);
      } else {
        this.marquee.init(JSON.parse(m));
      }
      if ($('#marquee')) {
        $('#marquee').css('z-index', '2');
      }
    },
    closeMarquee: function () {
      if (this.marquee) {
        this.marquee.close()
      }
    },
    loadMarqueePlugin (url, data) {
        if (!url) {
            return;
        }
        var script = document.createElement('script');
        script.src = url;
        script.type = 'text/javascript';
        script.onload = function() {
          var _this = this
          _this.marquee = new MarqueePlugin();
          try {
            _this.marquee.init(JSON.parse(data));
          } catch (e) {

          }
        }.bind(this);
        document.body.appendChild(script);
    }
  }

  // 接受语音互动请求
  window.on_cc_live_accept_interaction = function (data) {
    // if (!window.isSpeakThirdParty && live && live.livePlayer) {
    //   LivePlayer.closeSound()
    // }
    LivePlayer && LivePlayer.closeSound() // 连麦回音bug修复

    // 清除请求超时计时器
    live.interaction.clearRequestTimeoutTimer()
    if (window.isSpeakThirdParty) {
      live.interaction.initAgoraRTC(data)
    }

    DWLive.enterInteractionRoom()

    live.interaction.isInteractioning = true

    live.interaction.setCallingTimer()

    if (typeof window.on_cc_live_interaction_accept === 'function') {
      window.on_cc_live_interaction_accept(live.interaction.local.type, toJson(data))
    }
  }

  window.on_cc_live_interaction_disconnect_self = function (data) {
    if (window.isSpeakThirdParty) {
      live.interaction.leaveAgoraRTC()
      var type = live.interaction.local.type
      if (typeof window.on_cc_live_interaction_disconnect === 'function') {
        window.on_cc_live_interaction_disconnect(data, type)
      }
    }
    var uid = data.disconnectid
    var isPC = !!live.interaction.usersPcs[uid]
    if (uid != DWLive.viewerid && !isPC) {
      return
    }
    if (uid != DWLive.viewerid && isPC) {
      DWLive.hangupInteraction()
    }
    live.interaction.clearCallingTimer()
    live.interaction.disconnectInteraction(uid)
    // 与所有端断开连接
    if (uid == DWLive.viewerid || live.interaction.usersPcs.length == 0) {
      live.interaction.stopLocalStream()
      var type = live.interaction.local.type
      $('#videoInteractions').empty()
      $('#audioInteractions').empty()
      if ($('#interactionLocalVideo')[0]) {
        $('#interactionLocalVideo')[0].src = ''
      }
      if (type.video) {
        // DWLive.livePlayerInit()
        $('#livePlayer').show()
        LivePlayer.openSound()
      }
      if (!window.isSpeakThirdParty && typeof window.on_cc_live_interaction_disconnect === 'function') {
        window.on_cc_live_interaction_disconnect(data, type)
      }
    } else {
      // 断开其他人
    }
    window.isRequesting = false
  }

  window.on_cc_live_interaction_remote_media_self = function (type, chatuser, stream) {
    if (typeof window.on_cc_live_interaction_remote_media === 'function') {
      window.on_cc_live_interaction_remote_media(type, chatuser, stream)
    }
    window.isRequesting = false
    if (type.video) {
      //$('#livePlayer').replaceWith('<div id="livePlayer"></div>')
      $('#livePlayer').hide()
      var id = 'interactionRemoteVideo' + chatuser.id
      if ($('#' + id).length < 1) {
        $('#videoInteractions').append('<video cc-data="0" id="' + id + '" style="height: 100%; width: 100%;" autoplay></video>')
        $('#' + id)[0].srcObject = stream
      }
    } else {// 远程音频
      var id = 'interactionRemoteAudio' + chatuser.id
      if ($('#' + id).length < 1) {
        $('#audioInteractions').append('<audio cc-data="2" id="' + id + '" autoplay controls></audio>')
        $('#' + id)[0].srcObject = stream
      }
    }
  }

  // 主动连接语音聊天信息
  window.on_cc_live_interaction_chatusers = function (data) {
    data = toJson(data)
    $.each(data, function (index, chatuser) {
      if (chatuser.id == DWLive.viewerid) {
        return true
      }

      // 客户端只是和主播进行语音互动
      if (chatuser.role == 'publisher' && !chatuser.isMainSpeaker) {
        return true
      }

      live.interaction.createOfferPeerConnection(chatuser)
    })

  }

  // 接收互动信息
  window.on_cc_live_interaction_message = function (d) {
    var d = toJson(d)

    debug('Interaction', 'rtc互动信息:' + JSON.stringify(d))

    var toId = d.toid
    var fromId = d.fromid
    var fromName = d.fromname
    var type = d.type
    var data = d.data
    if (typeof data === 'string') {
      data = JSON.parse(data)
    }

    var event = d.event

    if (event === 'offer') {
      data.type = event

      live.interaction.createAnswerPeerConnection({
        id: fromId,
        name: fromName,
        type: type
      })

      var pc = live.interaction.usersPcs[fromId].pc
      if (!pc) {
        return
      }

      pc.setRemoteDescription(new nativeRTCSessionDescription(data))
      pc.createAnswer(function () {
      }, function (error) {
        debug('Interaction', 'Failure callback: ' + error)
      })

    } else if (event === 'answer') {
      var pc = live.interaction.usersPcs[fromId].pc
      if (!pc) {
        return
      }

      data.type = event

      debug('Interaction', 'answer spark_message信息:' + data)
      pc.setRemoteDescription(new nativeRTCSessionDescription(data))

      pc.receivedAnswer = true
      if (!pc.hasAddIce && pc.RTCICE) {
        pc.addIceCandidate(pc.RTCICE)
      }

    } else {
      var u = live.interaction.usersPcs[fromId]
      if (!u) {
        u = live.interaction.usersPcs[toId]
      }
      var pc = u ? u.pc : null

      if (!pc) {
        return
      }

      // 收到answer之后再addIce
      var ice = new RTCIceCandidate(data)
      if (pc.receivedAnswer) {
        pc.hasAddIce = true
        pc.addIceCandidate(ice)
      } else {
        pc.hasAddIce = false
        pc.RTCICE = ice
      }

    }
  }

  window.isDebug = false
  // 打印debug信息
  var debug = function (t, d) {
    if (!window.isDebug) {
      return
    }

    if (console && typeof console.log === 'function') {
      console.log(t, d)
    }
  }

  function toJson(data) {
    if (typeof data === 'string') {
      try {
        return JSON.parse(data)
      } catch (e) {
        return {}
      }
    }

    return data
  }

  
  
  DWLive.isSupportInteraction = window.live.interaction.isSupportInteraction

  window.onunload = function () {
    window.live.interaction.hangupInteraction()
  }
  window.onbeforeunload = function () {
    window.live.interaction.hangupInteraction()
  }

  // live player ready
  window._swfInit = function () {
    if (typeof window.on_cc_live_player_ready === 'function') {
      window.on_cc_live_player_ready()
    }
  }

  /**
   * Flash 加载完成
   * */
  window._swfOk = function (id) {
    if (typeof window.on_cc_swf_loading_completed === 'function') {
      window.on_cc_swf_loading_completed(id)
    }
    //直播播放器准备开始播放
    LivePlayer.isReady = true
  }

  function getDeltaTime() {
    // var b = LivePlayer.delay
    // if (isNaN(b) || b < 0) {
    //   b = 0
    // }
    // b = b * 1000

    // // 低延迟
    // if (MobileLive.isMobile() == 'isMobile') {
    //   if (b === 0) {
    //     return 5000
    //   } else {
    //     return 10000
    //   }
    // } else {
    //   if (b === 0) {
    //     return 1300
    //   } else {
    //     return 3000
    //   }
    // }
    return DWLive.docDelayTime * 1000
  }
  window.cc_doc_delaytime = function(time) {
    if (time) DWLive.docDelayTime = time
  }

  function getDelayTime() {
    var b = LivePlayer.delay
    if (isNaN(b) || b < 0) {
      b = 0
    }
    if (b) {
      // console.log("非低延迟模式");
    } else {
      // console.log("低延迟模式");
    }
    // b = b * 1000;

    // 低延迟
    if (MobileLive.isMobile() == 'isMobile') {
      if (b === 0) {
        return 5000
      } else {
        return 10000
      }
    } else {
      if (b === 0) {
        return 1300
      } else {
        return 3000
      }
    }
  }
})(window)